aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-06-24 23:28:17 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 18:25:44 -0400
commit3d7fc66dcd8d510aaa46ab9b914b632bc149b05c (patch)
tree256cf906d79359a90c462b5c1d08dc1969b6b7ed /drivers/scsi
parent5a54b1d576d1880eb249e906e0c8e2ffe64506d3 (diff)
[SCSI] bfa: Added HBA diagnostics support.
- Added diagnostics sub-module to BFA. - Implemented interface to perform memtest/loopback test and some other diagnostics tests. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/bfa/bfa_core.c16
-rw-r--r--drivers/scsi/bfa/bfa_defs.h58
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c580
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h141
-rw-r--r--drivers/scsi/bfa/bfa_modules.h3
-rw-r--r--drivers/scsi/bfa/bfa_svc.c417
-rw-r--r--drivers/scsi/bfa/bfa_svc.h47
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c206
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h83
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c14
-rw-r--r--drivers/scsi/bfa/bfi.h109
11 files changed, 1665 insertions, 9 deletions
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 04d362085360..e688ff72166d 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -25,6 +25,7 @@ BFA_TRC_FILE(HAL, CORE);
25 * BFA module list terminated by NULL 25 * BFA module list terminated by NULL
26 */ 26 */
27static struct bfa_module_s *hal_mods[] = { 27static struct bfa_module_s *hal_mods[] = {
28 &hal_mod_fcdiag,
28 &hal_mod_sgpg, 29 &hal_mod_sgpg,
29 &hal_mod_fcport, 30 &hal_mod_fcport,
30 &hal_mod_fcxp, 31 &hal_mod_fcxp,
@@ -41,7 +42,7 @@ static struct bfa_module_s *hal_mods[] = {
41static bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = { 42static bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = {
42 bfa_isr_unhandled, /* NONE */ 43 bfa_isr_unhandled, /* NONE */
43 bfa_isr_unhandled, /* BFI_MC_IOC */ 44 bfa_isr_unhandled, /* BFI_MC_IOC */
44 bfa_isr_unhandled, /* BFI_MC_DIAG */ 45 bfa_fcdiag_intr, /* BFI_MC_DIAG */
45 bfa_isr_unhandled, /* BFI_MC_FLASH */ 46 bfa_isr_unhandled, /* BFI_MC_FLASH */
46 bfa_isr_unhandled, /* BFI_MC_CEE */ 47 bfa_isr_unhandled, /* BFI_MC_CEE */
47 bfa_fcport_isr, /* BFI_MC_FCPORT */ 48 bfa_fcport_isr, /* BFI_MC_FCPORT */
@@ -143,6 +144,16 @@ bfa_com_flash_attach(struct bfa_s *bfa, bfa_boolean_t mincfg)
143 flash_dma->dma_curp, mincfg); 144 flash_dma->dma_curp, mincfg);
144} 145}
145 146
147static void
148bfa_com_diag_attach(struct bfa_s *bfa)
149{
150 struct bfa_diag_s *diag = BFA_DIAG_MOD(bfa);
151 struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
152
153 bfa_diag_attach(diag, &bfa->ioc, bfa, bfa_fcport_beacon, bfa->trcmod);
154 bfa_diag_memclaim(diag, diag_dma->kva_curp, diag_dma->dma_curp);
155}
156
146/* 157/*
147 * BFA IOC FC related definitions 158 * BFA IOC FC related definitions
148 */ 159 */
@@ -1383,6 +1394,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
1383 struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa); 1394 struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa);
1384 struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa); 1395 struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa);
1385 struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa); 1396 struct bfa_mem_dma_s *flash_dma = BFA_MEM_FLASH_DMA(bfa);
1397 struct bfa_mem_dma_s *diag_dma = BFA_MEM_DIAG_DMA(bfa);
1386 1398
1387 WARN_ON((cfg == NULL) || (meminfo == NULL)); 1399 WARN_ON((cfg == NULL) || (meminfo == NULL));
1388 1400
@@ -1404,6 +1416,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
1404 bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo()); 1416 bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo());
1405 bfa_mem_dma_setup(meminfo, flash_dma, 1417 bfa_mem_dma_setup(meminfo, flash_dma,
1406 bfa_flash_meminfo(cfg->drvcfg.min_cfg)); 1418 bfa_flash_meminfo(cfg->drvcfg.min_cfg));
1419 bfa_mem_dma_setup(meminfo, diag_dma, bfa_diag_meminfo());
1407} 1420}
1408 1421
1409/* 1422/*
@@ -1474,6 +1487,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1474 bfa_com_cee_attach(bfa); 1487 bfa_com_cee_attach(bfa);
1475 bfa_com_sfp_attach(bfa); 1488 bfa_com_sfp_attach(bfa);
1476 bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg); 1489 bfa_com_flash_attach(bfa, cfg->drvcfg.min_cfg);
1490 bfa_com_diag_attach(bfa);
1477} 1491}
1478 1492
1479/* 1493/*
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index 97ad07c4aee0..ddf13d74e4b0 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -132,7 +132,9 @@ enum bfa_status {
132 BFA_STATUS_EPROTOCOL = 6, /* Protocol error */ 132 BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
133 BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */ 133 BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */
134 BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */ 134 BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */
135 BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted */
135 BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */ 136 BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */
137 BFA_STATUS_HDMA_FAILED = 16, /* Host dma failed contact support */
136 BFA_STATUS_FLASH_BAD_LEN = 17, /* Flash bad length */ 138 BFA_STATUS_FLASH_BAD_LEN = 17, /* Flash bad length */
137 BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */ 139 BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */
138 BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */ 140 BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */
@@ -140,19 +142,25 @@ enum bfa_status {
140 BFA_STATUS_VPORT_MAX = 22, /* Reached max VPORT supported limit */ 142 BFA_STATUS_VPORT_MAX = 22, /* Reached max VPORT supported limit */
141 BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed setting */ 143 BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed setting */
142 BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */ 144 BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */
145 BFA_STATUS_CMD_NOTSUPP = 26, /* Command/API not supported */
143 BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */ 146 BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */
144 BFA_STATUS_PORT_OFFLINE = 34, /* Port is not online */ 147 BFA_STATUS_PORT_OFFLINE = 34, /* Port is not online */
145 BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */ 148 BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */
149 BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port */
146 BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the rport */ 150 BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the rport */
147 BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists 151 BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists
148 * contact support */ 152 * contact support */
149 BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */ 153 BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */
154 BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled */
150 BFA_STATUS_IOC_NON_OP = 61, /* IOC is not operational */ 155 BFA_STATUS_IOC_NON_OP = 61, /* IOC is not operational */
151 BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */ 156 BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version mismatch */
152 BFA_STATUS_DIAG_BUSY = 71, /* diag busy */ 157 BFA_STATUS_DIAG_BUSY = 71, /* diag busy */
158 BFA_STATUS_BEACON_ON = 72, /* Port Beacon already on */
153 BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */ 159 BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */
154 BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */ 160 BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */
155 BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */ 161 BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */
162 BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
163 BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
156 BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */ 164 BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */
157 BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot 165 BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
158 * configuration */ 166 * configuration */
@@ -881,6 +889,56 @@ struct bfa_flash_attr_s {
881 struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX]; 889 struct bfa_flash_part_attr_s part[BFA_FLASH_PART_MAX];
882}; 890};
883 891
892/*
893 * DIAG module specific
894 */
895#define LB_PATTERN_DEFAULT 0xB5B5B5B5
896#define QTEST_CNT_DEFAULT 10
897#define QTEST_PAT_DEFAULT LB_PATTERN_DEFAULT
898
899struct bfa_diag_memtest_s {
900 u8 algo;
901 u8 rsvd[7];
902};
903
904struct bfa_diag_memtest_result {
905 u32 status;
906 u32 addr;
907 u32 exp; /* expect value read from reg */
908 u32 act; /* actually value read */
909 u32 err_status; /* error status reg */
910 u32 err_status1; /* extra error info reg */
911 u32 err_addr; /* error address reg */
912 u8 algo;
913 u8 rsv[3];
914};
915
916struct bfa_diag_loopback_result_s {
917 u32 numtxmfrm; /* no. of transmit frame */
918 u32 numosffrm; /* no. of outstanding frame */
919 u32 numrcvfrm; /* no. of received good frame */
920 u32 badfrminf; /* mis-match info */
921 u32 badfrmnum; /* mis-match fram number */
922 u8 status; /* loopback test result */
923 u8 rsvd[3];
924};
925
926struct bfa_diag_ledtest_s {
927 u32 cmd; /* bfa_led_op_t */
928 u32 color; /* bfa_led_color_t */
929 u16 freq; /* no. of blinks every 10 secs */
930 u8 led; /* bitmap of LEDs to be tested */
931 u8 rsvd[5];
932};
933
934struct bfa_diag_loopback_s {
935 u32 loopcnt;
936 u32 pattern;
937 u8 lb_mode; /* bfa_port_opmode_t */
938 u8 speed; /* bfa_port_speed_t */
939 u8 rsvd[2];
940};
941
884#pragma pack() 942#pragma pack()
885 943
886#endif /* __BFA_DEFS_H__ */ 944#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 150607324132..31467780b619 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -4315,3 +4315,583 @@ bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4315 4315
4316 return BFA_STATUS_OK; 4316 return BFA_STATUS_OK;
4317} 4317}
4318
4319/*
4320 * DIAG module specific
4321 */
4322
4323#define BFA_DIAG_MEMTEST_TOV 50000 /* memtest timeout in msec */
4324#define BFA_DIAG_FWPING_TOV 1000 /* msec */
4325
4326/* IOC event handler */
4327static void
4328bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event)
4329{
4330 struct bfa_diag_s *diag = diag_arg;
4331
4332 bfa_trc(diag, event);
4333 bfa_trc(diag, diag->block);
4334 bfa_trc(diag, diag->fwping.lock);
4335 bfa_trc(diag, diag->tsensor.lock);
4336
4337 switch (event) {
4338 case BFA_IOC_E_DISABLED:
4339 case BFA_IOC_E_FAILED:
4340 if (diag->fwping.lock) {
4341 diag->fwping.status = BFA_STATUS_IOC_FAILURE;
4342 diag->fwping.cbfn(diag->fwping.cbarg,
4343 diag->fwping.status);
4344 diag->fwping.lock = 0;
4345 }
4346
4347 if (diag->tsensor.lock) {
4348 diag->tsensor.status = BFA_STATUS_IOC_FAILURE;
4349 diag->tsensor.cbfn(diag->tsensor.cbarg,
4350 diag->tsensor.status);
4351 diag->tsensor.lock = 0;
4352 }
4353
4354 if (diag->block) {
4355 if (diag->timer_active) {
4356 bfa_timer_stop(&diag->timer);
4357 diag->timer_active = 0;
4358 }
4359
4360 diag->status = BFA_STATUS_IOC_FAILURE;
4361 diag->cbfn(diag->cbarg, diag->status);
4362 diag->block = 0;
4363 }
4364 break;
4365
4366 default:
4367 break;
4368 }
4369}
4370
4371static void
4372bfa_diag_memtest_done(void *cbarg)
4373{
4374 struct bfa_diag_s *diag = cbarg;
4375 struct bfa_ioc_s *ioc = diag->ioc;
4376 struct bfa_diag_memtest_result *res = diag->result;
4377 u32 loff = BFI_BOOT_MEMTEST_RES_ADDR;
4378 u32 pgnum, pgoff, i;
4379
4380 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
4381 pgoff = PSS_SMEM_PGOFF(loff);
4382
4383 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
4384
4385 for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /
4386 sizeof(u32)); i++) {
4387 /* read test result from smem */
4388 *((u32 *) res + i) =
4389 bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
4390 loff += sizeof(u32);
4391 }
4392
4393 /* Reset IOC fwstates to BFI_IOC_UNINIT */
4394 bfa_ioc_reset_fwstate(ioc);
4395
4396 res->status = swab32(res->status);
4397 bfa_trc(diag, res->status);
4398
4399 if (res->status == BFI_BOOT_MEMTEST_RES_SIG)
4400 diag->status = BFA_STATUS_OK;
4401 else {
4402 diag->status = BFA_STATUS_MEMTEST_FAILED;
4403 res->addr = swab32(res->addr);
4404 res->exp = swab32(res->exp);
4405 res->act = swab32(res->act);
4406 res->err_status = swab32(res->err_status);
4407 res->err_status1 = swab32(res->err_status1);
4408 res->err_addr = swab32(res->err_addr);
4409 bfa_trc(diag, res->addr);
4410 bfa_trc(diag, res->exp);
4411 bfa_trc(diag, res->act);
4412 bfa_trc(diag, res->err_status);
4413 bfa_trc(diag, res->err_status1);
4414 bfa_trc(diag, res->err_addr);
4415 }
4416 diag->timer_active = 0;
4417 diag->cbfn(diag->cbarg, diag->status);
4418 diag->block = 0;
4419}
4420
4421/*
4422 * Firmware ping
4423 */
4424
4425/*
4426 * Perform DMA test directly
4427 */
4428static void
4429diag_fwping_send(struct bfa_diag_s *diag)
4430{
4431 struct bfi_diag_fwping_req_s *fwping_req;
4432 u32 i;
4433
4434 bfa_trc(diag, diag->fwping.dbuf_pa);
4435
4436 /* fill DMA area with pattern */
4437 for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++)
4438 *((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data;
4439
4440 /* Fill mbox msg */
4441 fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg;
4442
4443 /* Setup SG list */
4444 bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ,
4445 diag->fwping.dbuf_pa);
4446 /* Set up dma count */
4447 fwping_req->count = cpu_to_be32(diag->fwping.count);
4448 /* Set up data pattern */
4449 fwping_req->data = diag->fwping.data;
4450
4451 /* build host command */
4452 bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING,
4453 bfa_ioc_portid(diag->ioc));
4454
4455 /* send mbox cmd */
4456 bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd);
4457}
4458
4459static void
4460diag_fwping_comp(struct bfa_diag_s *diag,
4461 struct bfi_diag_fwping_rsp_s *diag_rsp)
4462{
4463 u32 rsp_data = diag_rsp->data;
4464 u8 rsp_dma_status = diag_rsp->dma_status;
4465
4466 bfa_trc(diag, rsp_data);
4467 bfa_trc(diag, rsp_dma_status);
4468
4469 if (rsp_dma_status == BFA_STATUS_OK) {
4470 u32 i, pat;
4471 pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) :
4472 diag->fwping.data;
4473 /* Check mbox data */
4474 if (diag->fwping.data != rsp_data) {
4475 bfa_trc(diag, rsp_data);
4476 diag->fwping.result->dmastatus =
4477 BFA_STATUS_DATACORRUPTED;
4478 diag->fwping.status = BFA_STATUS_DATACORRUPTED;
4479 diag->fwping.cbfn(diag->fwping.cbarg,
4480 diag->fwping.status);
4481 diag->fwping.lock = 0;
4482 return;
4483 }
4484 /* Check dma pattern */
4485 for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) {
4486 if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) {
4487 bfa_trc(diag, i);
4488 bfa_trc(diag, pat);
4489 bfa_trc(diag,
4490 *((u32 *)diag->fwping.dbuf_kva + i));
4491 diag->fwping.result->dmastatus =
4492 BFA_STATUS_DATACORRUPTED;
4493 diag->fwping.status = BFA_STATUS_DATACORRUPTED;
4494 diag->fwping.cbfn(diag->fwping.cbarg,
4495 diag->fwping.status);
4496 diag->fwping.lock = 0;
4497 return;
4498 }
4499 }
4500 diag->fwping.result->dmastatus = BFA_STATUS_OK;
4501 diag->fwping.status = BFA_STATUS_OK;
4502 diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
4503 diag->fwping.lock = 0;
4504 } else {
4505 diag->fwping.status = BFA_STATUS_HDMA_FAILED;
4506 diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
4507 diag->fwping.lock = 0;
4508 }
4509}
4510
4511/*
4512 * Temperature Sensor
4513 */
4514
4515static void
4516diag_tempsensor_send(struct bfa_diag_s *diag)
4517{
4518 struct bfi_diag_ts_req_s *msg;
4519
4520 msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg;
4521 bfa_trc(diag, msg->temp);
4522 /* build host command */
4523 bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR,
4524 bfa_ioc_portid(diag->ioc));
4525 /* send mbox cmd */
4526 bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd);
4527}
4528
4529static void
4530diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
4531{
4532 if (!diag->tsensor.lock) {
4533 /* receiving response after ioc failure */
4534 bfa_trc(diag, diag->tsensor.lock);
4535 return;
4536 }
4537
4538 /*
4539 * ASIC junction tempsensor is a reg read operation
4540 * it will always return OK
4541 */
4542 diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
4543 diag->tsensor.temp->ts_junc = rsp->ts_junc;
4544 diag->tsensor.temp->ts_brd = rsp->ts_brd;
4545 diag->tsensor.temp->status = BFA_STATUS_OK;
4546
4547 if (rsp->ts_brd) {
4548 if (rsp->status == BFA_STATUS_OK) {
4549 diag->tsensor.temp->brd_temp =
4550 be16_to_cpu(rsp->brd_temp);
4551 } else {
4552 bfa_trc(diag, rsp->status);
4553 diag->tsensor.temp->brd_temp = 0;
4554 diag->tsensor.temp->status = BFA_STATUS_DEVBUSY;
4555 }
4556 }
4557 bfa_trc(diag, rsp->ts_junc);
4558 bfa_trc(diag, rsp->temp);
4559 bfa_trc(diag, rsp->ts_brd);
4560 bfa_trc(diag, rsp->brd_temp);
4561 diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
4562 diag->tsensor.lock = 0;
4563}
4564
4565/*
4566 * LED Test command
4567 */
4568static void
4569diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
4570{
4571 struct bfi_diag_ledtest_req_s *msg;
4572
4573 msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg;
4574 /* build host command */
4575 bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST,
4576 bfa_ioc_portid(diag->ioc));
4577
4578 /*
4579 * convert the freq from N blinks per 10 sec to
4580 * crossbow ontime value. We do it here because division is need
4581 */
4582 if (ledtest->freq)
4583 ledtest->freq = 500 / ledtest->freq;
4584
4585 if (ledtest->freq == 0)
4586 ledtest->freq = 1;
4587
4588 bfa_trc(diag, ledtest->freq);
4589 /* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */
4590 msg->cmd = (u8) ledtest->cmd;
4591 msg->color = (u8) ledtest->color;
4592 msg->portid = bfa_ioc_portid(diag->ioc);
4593 msg->led = ledtest->led;
4594 msg->freq = cpu_to_be16(ledtest->freq);
4595
4596 /* send mbox cmd */
4597 bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd);
4598}
4599
4600static void
4601diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s * msg)
4602{
4603 bfa_trc(diag, diag->ledtest.lock);
4604 diag->ledtest.lock = BFA_FALSE;
4605 /* no bfa_cb_queue is needed because driver is not waiting */
4606}
4607
4608/*
4609 * Port beaconing
4610 */
4611static void
4612diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec)
4613{
4614 struct bfi_diag_portbeacon_req_s *msg;
4615
4616 msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg;
4617 /* build host command */
4618 bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON,
4619 bfa_ioc_portid(diag->ioc));
4620 msg->beacon = beacon;
4621 msg->period = cpu_to_be32(sec);
4622 /* send mbox cmd */
4623 bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd);
4624}
4625
4626static void
4627diag_portbeacon_comp(struct bfa_diag_s *diag)
4628{
4629 bfa_trc(diag, diag->beacon.state);
4630 diag->beacon.state = BFA_FALSE;
4631 if (diag->cbfn_beacon)
4632 diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e);
4633}
4634
4635/*
4636 * Diag hmbox handler
4637 */
4638void
4639bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)
4640{
4641 struct bfa_diag_s *diag = diagarg;
4642
4643 switch (msg->mh.msg_id) {
4644 case BFI_DIAG_I2H_PORTBEACON:
4645 diag_portbeacon_comp(diag);
4646 break;
4647 case BFI_DIAG_I2H_FWPING:
4648 diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg);
4649 break;
4650 case BFI_DIAG_I2H_TEMPSENSOR:
4651 diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg);
4652 break;
4653 case BFI_DIAG_I2H_LEDTEST:
4654 diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg);
4655 break;
4656 default:
4657 bfa_trc(diag, msg->mh.msg_id);
4658 WARN_ON(1);
4659 }
4660}
4661
4662/*
4663 * Gen RAM Test
4664 *
4665 * @param[in] *diag - diag data struct
4666 * @param[in] *memtest - mem test params input from upper layer,
4667 * @param[in] pattern - mem test pattern
4668 * @param[in] *result - mem test result
4669 * @param[in] cbfn - mem test callback functioin
4670 * @param[in] cbarg - callback functioin arg
4671 *
4672 * @param[out]
4673 */
4674bfa_status_t
4675bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest,
4676 u32 pattern, struct bfa_diag_memtest_result *result,
4677 bfa_cb_diag_t cbfn, void *cbarg)
4678{
4679 bfa_trc(diag, pattern);
4680
4681 if (!bfa_ioc_adapter_is_disabled(diag->ioc))
4682 return BFA_STATUS_ADAPTER_ENABLED;
4683
4684 /* check to see if there is another destructive diag cmd running */
4685 if (diag->block) {
4686 bfa_trc(diag, diag->block);
4687 return BFA_STATUS_DEVBUSY;
4688 } else
4689 diag->block = 1;
4690
4691 diag->result = result;
4692 diag->cbfn = cbfn;
4693 diag->cbarg = cbarg;
4694
4695 /* download memtest code and take LPU0 out of reset */
4696 bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS);
4697
4698 bfa_timer_begin(diag->ioc->timer_mod, &diag->timer,
4699 bfa_diag_memtest_done, diag, BFA_DIAG_MEMTEST_TOV);
4700 diag->timer_active = 1;
4701 return BFA_STATUS_OK;
4702}
4703
4704/*
4705 * DIAG firmware ping command
4706 *
4707 * @param[in] *diag - diag data struct
4708 * @param[in] cnt - dma loop count for testing PCIE
4709 * @param[in] data - data pattern to pass in fw
4710 * @param[in] *result - pt to bfa_diag_fwping_result_t data struct
4711 * @param[in] cbfn - callback function
4712 * @param[in] *cbarg - callback functioin arg
4713 *
4714 * @param[out]
4715 */
4716bfa_status_t
4717bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data,
4718 struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn,
4719 void *cbarg)
4720{
4721 bfa_trc(diag, cnt);
4722 bfa_trc(diag, data);
4723
4724 if (!bfa_ioc_is_operational(diag->ioc))
4725 return BFA_STATUS_IOC_NON_OP;
4726
4727 if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) &&
4728 ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH))
4729 return BFA_STATUS_CMD_NOTSUPP;
4730
4731 /* check to see if there is another destructive diag cmd running */
4732 if (diag->block || diag->fwping.lock) {
4733 bfa_trc(diag, diag->block);
4734 bfa_trc(diag, diag->fwping.lock);
4735 return BFA_STATUS_DEVBUSY;
4736 }
4737
4738 /* Initialization */
4739 diag->fwping.lock = 1;
4740 diag->fwping.cbfn = cbfn;
4741 diag->fwping.cbarg = cbarg;
4742 diag->fwping.result = result;
4743 diag->fwping.data = data;
4744 diag->fwping.count = cnt;
4745
4746 /* Init test results */
4747 diag->fwping.result->data = 0;
4748 diag->fwping.result->status = BFA_STATUS_OK;
4749
4750 /* kick off the first ping */
4751 diag_fwping_send(diag);
4752 return BFA_STATUS_OK;
4753}
4754
4755/*
4756 * Read Temperature Sensor
4757 *
4758 * @param[in] *diag - diag data struct
4759 * @param[in] *result - pt to bfa_diag_temp_t data struct
4760 * @param[in] cbfn - callback function
4761 * @param[in] *cbarg - callback functioin arg
4762 *
4763 * @param[out]
4764 */
4765bfa_status_t
4766bfa_diag_tsensor_query(struct bfa_diag_s *diag,
4767 struct bfa_diag_results_tempsensor_s *result,
4768 bfa_cb_diag_t cbfn, void *cbarg)
4769{
4770 /* check to see if there is a destructive diag cmd running */
4771 if (diag->block || diag->tsensor.lock) {
4772 bfa_trc(diag, diag->block);
4773 bfa_trc(diag, diag->tsensor.lock);
4774 return BFA_STATUS_DEVBUSY;
4775 }
4776
4777 if (!bfa_ioc_is_operational(diag->ioc))
4778 return BFA_STATUS_IOC_NON_OP;
4779
4780 /* Init diag mod params */
4781 diag->tsensor.lock = 1;
4782 diag->tsensor.temp = result;
4783 diag->tsensor.cbfn = cbfn;
4784 diag->tsensor.cbarg = cbarg;
4785
4786 /* Send msg to fw */
4787 diag_tempsensor_send(diag);
4788
4789 return BFA_STATUS_OK;
4790}
4791
4792/*
4793 * LED Test command
4794 *
4795 * @param[in] *diag - diag data struct
4796 * @param[in] *ledtest - pt to ledtest data structure
4797 *
4798 * @param[out]
4799 */
4800bfa_status_t
4801bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
4802{
4803 bfa_trc(diag, ledtest->cmd);
4804
4805 if (!bfa_ioc_is_operational(diag->ioc))
4806 return BFA_STATUS_IOC_NON_OP;
4807
4808 if (diag->beacon.state)
4809 return BFA_STATUS_BEACON_ON;
4810
4811 if (diag->ledtest.lock)
4812 return BFA_STATUS_LEDTEST_OP;
4813
4814 /* Send msg to fw */
4815 diag->ledtest.lock = BFA_TRUE;
4816 diag_ledtest_send(diag, ledtest);
4817
4818 return BFA_STATUS_OK;
4819}
4820
4821/*
4822 * Port beaconing command
4823 *
4824 * @param[in] *diag - diag data struct
4825 * @param[in] beacon - port beaconing 1:ON 0:OFF
4826 * @param[in] link_e2e_beacon - link beaconing 1:ON 0:OFF
4827 * @param[in] sec - beaconing duration in seconds
4828 *
4829 * @param[out]
4830 */
4831bfa_status_t
4832bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon,
4833 bfa_boolean_t link_e2e_beacon, uint32_t sec)
4834{
4835 bfa_trc(diag, beacon);
4836 bfa_trc(diag, link_e2e_beacon);
4837 bfa_trc(diag, sec);
4838
4839 if (!bfa_ioc_is_operational(diag->ioc))
4840 return BFA_STATUS_IOC_NON_OP;
4841
4842 if (diag->ledtest.lock)
4843 return BFA_STATUS_LEDTEST_OP;
4844
4845 if (diag->beacon.state && beacon) /* beacon alread on */
4846 return BFA_STATUS_BEACON_ON;
4847
4848 diag->beacon.state = beacon;
4849 diag->beacon.link_e2e = link_e2e_beacon;
4850 if (diag->cbfn_beacon)
4851 diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon);
4852
4853 /* Send msg to fw */
4854 diag_portbeacon_send(diag, beacon, sec);
4855
4856 return BFA_STATUS_OK;
4857}
4858
4859/*
4860 * Return DMA memory needed by diag module.
4861 */
4862u32
4863bfa_diag_meminfo(void)
4864{
4865 return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4866}
4867
4868/*
4869 * Attach virtual and physical memory for Diag.
4870 */
4871void
4872bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
4873 bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod)
4874{
4875 diag->dev = dev;
4876 diag->ioc = ioc;
4877 diag->trcmod = trcmod;
4878
4879 diag->block = 0;
4880 diag->cbfn = NULL;
4881 diag->cbarg = NULL;
4882 diag->result = NULL;
4883 diag->cbfn_beacon = cbfn_beacon;
4884
4885 bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag);
4886 bfa_q_qe_init(&diag->ioc_notify);
4887 bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag);
4888 list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q);
4889}
4890
4891void
4892bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa)
4893{
4894 diag->fwping.dbuf_kva = dm_kva;
4895 diag->fwping.dbuf_pa = dm_pa;
4896 memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ);
4897}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index c302b996b920..5bcab540ea60 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -491,6 +491,147 @@ void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc,
491void bfa_flash_memclaim(struct bfa_flash_s *flash, 491void bfa_flash_memclaim(struct bfa_flash_s *flash,
492 u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg); 492 u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
493 493
494/*
495 * DIAG module specific
496 */
497
498typedef void (*bfa_cb_diag_t) (void *cbarg, bfa_status_t status);
499typedef void (*bfa_cb_diag_beacon_t) (void *dev, bfa_boolean_t beacon,
500 bfa_boolean_t link_e2e_beacon);
501
502/*
503 * Firmware ping test results
504 */
505struct bfa_diag_results_fwping {
506 u32 data; /* store the corrupted data */
507 u32 status;
508 u32 dmastatus;
509 u8 rsvd[4];
510};
511
512struct bfa_diag_qtest_result_s {
513 u32 status;
514 u16 count; /* sucessful queue test count */
515 u8 queue;
516 u8 rsvd; /* 64-bit align */
517};
518
519/*
520 * Firmware ping test results
521 */
522struct bfa_diag_fwping_s {
523 struct bfa_diag_results_fwping *result;
524 bfa_cb_diag_t cbfn;
525 void *cbarg;
526 u32 data;
527 u8 lock;
528 u8 rsv[3];
529 u32 status;
530 u32 count;
531 struct bfa_mbox_cmd_s mbcmd;
532 u8 *dbuf_kva; /* dma buf virtual address */
533 u64 dbuf_pa; /* dma buf physical address */
534};
535
536/*
537 * Temperature sensor query results
538 */
539struct bfa_diag_results_tempsensor_s {
540 u32 status;
541 u16 temp; /* 10-bit A/D value */
542 u16 brd_temp; /* 9-bit board temp */
543 u8 ts_junc; /* show junction tempsensor */
544 u8 ts_brd; /* show board tempsensor */
545 u8 rsvd[6]; /* keep 8 bytes alignment */
546};
547
548struct bfa_diag_tsensor_s {
549 bfa_cb_diag_t cbfn;
550 void *cbarg;
551 struct bfa_diag_results_tempsensor_s *temp;
552 u8 lock;
553 u8 rsv[3];
554 u32 status;
555 struct bfa_mbox_cmd_s mbcmd;
556};
557
558struct bfa_diag_sfpshow_s {
559 struct sfp_mem_s *sfpmem;
560 bfa_cb_diag_t cbfn;
561 void *cbarg;
562 u8 lock;
563 u8 static_data;
564 u8 rsv[2];
565 u32 status;
566 struct bfa_mbox_cmd_s mbcmd;
567 u8 *dbuf_kva; /* dma buf virtual address */
568 u64 dbuf_pa; /* dma buf physical address */
569};
570
571struct bfa_diag_led_s {
572 struct bfa_mbox_cmd_s mbcmd;
573 bfa_boolean_t lock; /* 1: ledtest is operating */
574};
575
576struct bfa_diag_beacon_s {
577 struct bfa_mbox_cmd_s mbcmd;
578 bfa_boolean_t state; /* port beacon state */
579 bfa_boolean_t link_e2e; /* link beacon state */
580};
581
582struct bfa_diag_s {
583 void *dev;
584 struct bfa_ioc_s *ioc;
585 struct bfa_trc_mod_s *trcmod;
586 struct bfa_diag_fwping_s fwping;
587 struct bfa_diag_tsensor_s tsensor;
588 struct bfa_diag_sfpshow_s sfpshow;
589 struct bfa_diag_led_s ledtest;
590 struct bfa_diag_beacon_s beacon;
591 void *result;
592 struct bfa_timer_s timer;
593 bfa_cb_diag_beacon_t cbfn_beacon;
594 bfa_cb_diag_t cbfn;
595 void *cbarg;
596 u8 block;
597 u8 timer_active;
598 u8 rsvd[2];
599 u32 status;
600 struct bfa_ioc_notify_s ioc_notify;
601 struct bfa_mem_dma_s diag_dma;
602};
603
604#define BFA_DIAG_MOD(__bfa) (&(__bfa)->modules.diag_mod)
605#define BFA_MEM_DIAG_DMA(__bfa) (&(BFA_DIAG_MOD(__bfa)->diag_dma))
606
607u32 bfa_diag_meminfo(void);
608void bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa);
609void bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
610 bfa_cb_diag_beacon_t cbfn_beacon,
611 struct bfa_trc_mod_s *trcmod);
612bfa_status_t bfa_diag_reg_read(struct bfa_diag_s *diag, u32 offset,
613 u32 len, u32 *buf, u32 force);
614bfa_status_t bfa_diag_reg_write(struct bfa_diag_s *diag, u32 offset,
615 u32 len, u32 value, u32 force);
616bfa_status_t bfa_diag_tsensor_query(struct bfa_diag_s *diag,
617 struct bfa_diag_results_tempsensor_s *result,
618 bfa_cb_diag_t cbfn, void *cbarg);
619bfa_status_t bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt,
620 u32 pattern, struct bfa_diag_results_fwping *result,
621 bfa_cb_diag_t cbfn, void *cbarg);
622bfa_status_t bfa_diag_sfpshow(struct bfa_diag_s *diag,
623 struct sfp_mem_s *sfpmem, u8 static_data,
624 bfa_cb_diag_t cbfn, void *cbarg);
625bfa_status_t bfa_diag_memtest(struct bfa_diag_s *diag,
626 struct bfa_diag_memtest_s *memtest, u32 pattern,
627 struct bfa_diag_memtest_result *result,
628 bfa_cb_diag_t cbfn, void *cbarg);
629bfa_status_t bfa_diag_ledtest(struct bfa_diag_s *diag,
630 struct bfa_diag_ledtest_s *ledtest);
631bfa_status_t bfa_diag_beacon_port(struct bfa_diag_s *diag,
632 bfa_boolean_t beacon, bfa_boolean_t link_e2e_beacon,
633 u32 sec);
634
494#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func) 635#define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func)
495#define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id) 636#define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id)
496#define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva) 637#define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva)
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h
index f7783f0d3267..c6b2fe7ed960 100644
--- a/drivers/scsi/bfa/bfa_modules.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -29,6 +29,7 @@
29#include "bfa_port.h" 29#include "bfa_port.h"
30 30
31struct bfa_modules_s { 31struct bfa_modules_s {
32 struct bfa_fcdiag_s fcdiag; /* fcdiag module */
32 struct bfa_fcport_s fcport; /* fc port module */ 33 struct bfa_fcport_s fcport; /* fc port module */
33 struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */ 34 struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */
34 struct bfa_lps_mod_s lps_mod; /* fcxp module */ 35 struct bfa_lps_mod_s lps_mod; /* fcxp module */
@@ -41,6 +42,7 @@ struct bfa_modules_s {
41 struct bfa_cee_s cee; /* CEE Module */ 42 struct bfa_cee_s cee; /* CEE Module */
42 struct bfa_sfp_s sfp; /* SFP module */ 43 struct bfa_sfp_s sfp; /* SFP module */
43 struct bfa_flash_s flash; /* flash module */ 44 struct bfa_flash_s flash; /* flash module */
45 struct bfa_diag_s diag_mod; /* diagnostics module */
44}; 46};
45 47
46/* 48/*
@@ -119,6 +121,7 @@ struct bfa_s {
119}; 121};
120 122
121extern bfa_boolean_t bfa_auto_recover; 123extern bfa_boolean_t bfa_auto_recover;
124extern struct bfa_module_s hal_mod_fcdiag;
122extern struct bfa_module_s hal_mod_sgpg; 125extern struct bfa_module_s hal_mod_sgpg;
123extern struct bfa_module_s hal_mod_fcport; 126extern struct bfa_module_s hal_mod_fcport;
124extern struct bfa_module_s hal_mod_fcxp; 127extern struct bfa_module_s hal_mod_fcxp;
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index d7853e698d01..21caaefce99f 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -21,6 +21,7 @@
21#include "bfa_modules.h" 21#include "bfa_modules.h"
22 22
23BFA_TRC_FILE(HAL, FCXP); 23BFA_TRC_FILE(HAL, FCXP);
24BFA_MODULE(fcdiag);
24BFA_MODULE(fcxp); 25BFA_MODULE(fcxp);
25BFA_MODULE(sgpg); 26BFA_MODULE(sgpg);
26BFA_MODULE(lps); 27BFA_MODULE(lps);
@@ -3872,6 +3873,22 @@ bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
3872 3873
3873} 3874}
3874 3875
3876void
3877bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
3878 bfa_boolean_t link_e2e_beacon)
3879{
3880 struct bfa_s *bfa = dev;
3881 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3882
3883 bfa_trc(bfa, beacon);
3884 bfa_trc(bfa, link_e2e_beacon);
3885 bfa_trc(bfa, fcport->beacon);
3886 bfa_trc(bfa, fcport->link_e2e_beacon);
3887
3888 fcport->beacon = beacon;
3889 fcport->link_e2e_beacon = link_e2e_beacon;
3890}
3891
3875bfa_boolean_t 3892bfa_boolean_t
3876bfa_fcport_is_linkup(struct bfa_s *bfa) 3893bfa_fcport_is_linkup(struct bfa_s *bfa)
3877{ 3894{
@@ -5224,3 +5241,403 @@ bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5224 list_add_tail(qe, &mod->uf_unused_q); 5241 list_add_tail(qe, &mod->uf_unused_q);
5225 } 5242 }
5226} 5243}
5244
5245/*
5246 * BFA fcdiag module
5247 */
5248#define BFA_DIAG_QTEST_TOV 1000 /* msec */
5249
5250/*
5251 * Set port status to busy
5252 */
5253static void
5254bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
5255{
5256 struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
5257
5258 if (fcdiag->lb.lock)
5259 fcport->diag_busy = BFA_TRUE;
5260 else
5261 fcport->diag_busy = BFA_FALSE;
5262}
5263
5264static void
5265bfa_fcdiag_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
5266 struct bfa_s *bfa)
5267{
5268}
5269
5270static void
5271bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5272 struct bfa_pcidev_s *pcidev)
5273{
5274 struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5275 fcdiag->bfa = bfa;
5276 fcdiag->trcmod = bfa->trcmod;
5277 /* The common DIAG attach bfa_diag_attach() will do all memory claim */
5278}
5279
5280static void
5281bfa_fcdiag_iocdisable(struct bfa_s *bfa)
5282{
5283 struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5284 bfa_trc(fcdiag, fcdiag->lb.lock);
5285 if (fcdiag->lb.lock) {
5286 fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
5287 fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5288 fcdiag->lb.lock = 0;
5289 bfa_fcdiag_set_busy_status(fcdiag);
5290 }
5291}
5292
5293static void
5294bfa_fcdiag_detach(struct bfa_s *bfa)
5295{
5296}
5297
5298static void
5299bfa_fcdiag_start(struct bfa_s *bfa)
5300{
5301}
5302
5303static void
5304bfa_fcdiag_stop(struct bfa_s *bfa)
5305{
5306}
5307
5308static void
5309bfa_fcdiag_queuetest_timeout(void *cbarg)
5310{
5311 struct bfa_fcdiag_s *fcdiag = cbarg;
5312 struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5313
5314 bfa_trc(fcdiag, fcdiag->qtest.all);
5315 bfa_trc(fcdiag, fcdiag->qtest.count);
5316
5317 fcdiag->qtest.timer_active = 0;
5318
5319 res->status = BFA_STATUS_ETIMER;
5320 res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5321 if (fcdiag->qtest.all)
5322 res->queue = fcdiag->qtest.all;
5323
5324 bfa_trc(fcdiag, BFA_STATUS_ETIMER);
5325 fcdiag->qtest.status = BFA_STATUS_ETIMER;
5326 fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5327 fcdiag->qtest.lock = 0;
5328}
5329
5330static bfa_status_t
5331bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
5332{
5333 u32 i;
5334 struct bfi_diag_qtest_req_s *req;
5335
5336 req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
5337 if (!req)
5338 return BFA_STATUS_DEVBUSY;
5339
5340 /* build host command */
5341 bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
5342 bfa_fn_lpu(fcdiag->bfa));
5343
5344 for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
5345 req->data[i] = QTEST_PAT_DEFAULT;
5346
5347 bfa_trc(fcdiag, fcdiag->qtest.queue);
5348 /* ring door bell */
5349 bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
5350 return BFA_STATUS_OK;
5351}
5352
5353static void
5354bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
5355 bfi_diag_qtest_rsp_t *rsp)
5356{
5357 struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5358 bfa_status_t status = BFA_STATUS_OK;
5359 int i;
5360
5361 /* Check timer, should still be active */
5362 if (!fcdiag->qtest.timer_active) {
5363 bfa_trc(fcdiag, fcdiag->qtest.timer_active);
5364 return;
5365 }
5366
5367 /* update count */
5368 fcdiag->qtest.count--;
5369
5370 /* Check result */
5371 for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
5372 if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
5373 res->status = BFA_STATUS_DATACORRUPTED;
5374 break;
5375 }
5376 }
5377
5378 if (res->status == BFA_STATUS_OK) {
5379 if (fcdiag->qtest.count > 0) {
5380 status = bfa_fcdiag_queuetest_send(fcdiag);
5381 if (status == BFA_STATUS_OK)
5382 return;
5383 else
5384 res->status = status;
5385 } else if (fcdiag->qtest.all > 0 &&
5386 fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
5387 fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5388 fcdiag->qtest.queue++;
5389 status = bfa_fcdiag_queuetest_send(fcdiag);
5390 if (status == BFA_STATUS_OK)
5391 return;
5392 else
5393 res->status = status;
5394 }
5395 }
5396
5397 /* Stop timer when we comp all queue */
5398 if (fcdiag->qtest.timer_active) {
5399 bfa_timer_stop(&fcdiag->qtest.timer);
5400 fcdiag->qtest.timer_active = 0;
5401 }
5402 res->queue = fcdiag->qtest.queue;
5403 res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5404 bfa_trc(fcdiag, res->count);
5405 bfa_trc(fcdiag, res->status);
5406 fcdiag->qtest.status = res->status;
5407 fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5408 fcdiag->qtest.lock = 0;
5409}
5410
5411static void
5412bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
5413 struct bfi_diag_lb_rsp_s *rsp)
5414{
5415 struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
5416
5417 res->numtxmfrm = be32_to_cpu(rsp->res.numtxmfrm);
5418 res->numosffrm = be32_to_cpu(rsp->res.numosffrm);
5419 res->numrcvfrm = be32_to_cpu(rsp->res.numrcvfrm);
5420 res->badfrminf = be32_to_cpu(rsp->res.badfrminf);
5421 res->badfrmnum = be32_to_cpu(rsp->res.badfrmnum);
5422 res->status = rsp->res.status;
5423 fcdiag->lb.status = rsp->res.status;
5424 bfa_trc(fcdiag, fcdiag->lb.status);
5425 fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5426 fcdiag->lb.lock = 0;
5427 bfa_fcdiag_set_busy_status(fcdiag);
5428}
5429
5430static bfa_status_t
5431bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
5432 struct bfa_diag_loopback_s *loopback)
5433{
5434 struct bfi_diag_lb_req_s *lb_req;
5435
5436 lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
5437 if (!lb_req)
5438 return BFA_STATUS_DEVBUSY;
5439
5440 /* build host command */
5441 bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
5442 bfa_fn_lpu(fcdiag->bfa));
5443
5444 lb_req->lb_mode = loopback->lb_mode;
5445 lb_req->speed = loopback->speed;
5446 lb_req->loopcnt = loopback->loopcnt;
5447 lb_req->pattern = loopback->pattern;
5448
5449 /* ring door bell */
5450 bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
5451
5452 bfa_trc(fcdiag, loopback->lb_mode);
5453 bfa_trc(fcdiag, loopback->speed);
5454 bfa_trc(fcdiag, loopback->loopcnt);
5455 bfa_trc(fcdiag, loopback->pattern);
5456 return BFA_STATUS_OK;
5457}
5458
5459/*
5460 * cpe/rme intr handler
5461 */
5462void
5463bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5464{
5465 struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5466
5467 switch (msg->mhdr.msg_id) {
5468 case BFI_DIAG_I2H_LOOPBACK:
5469 bfa_fcdiag_loopback_comp(fcdiag,
5470 (struct bfi_diag_lb_rsp_s *) msg);
5471 break;
5472 case BFI_DIAG_I2H_QTEST:
5473 bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
5474 break;
5475 default:
5476 bfa_trc(fcdiag, msg->mhdr.msg_id);
5477 WARN_ON(1);
5478 }
5479}
5480
5481/*
5482 * Loopback test
5483 *
5484 * @param[in] *bfa - bfa data struct
5485 * @param[in] opmode - port operation mode
5486 * @param[in] speed - port speed
5487 * @param[in] lpcnt - loop count
5488 * @param[in] pat - pattern to build packet
5489 * @param[in] *result - pt to bfa_diag_loopback_result_t data struct
5490 * @param[in] cbfn - callback function
5491 * @param[in] cbarg - callback functioin arg
5492 *
5493 * @param[out]
5494 */
5495bfa_status_t
5496bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
5497 enum bfa_port_speed speed, u32 lpcnt, u32 pat,
5498 struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
5499 void *cbarg)
5500{
5501 struct bfa_diag_loopback_s loopback;
5502 struct bfa_port_attr_s attr;
5503 bfa_status_t status;
5504 struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5505
5506 if (!bfa_iocfc_is_operational(bfa))
5507 return BFA_STATUS_IOC_NON_OP;
5508
5509 /* if port is PBC disabled, return error */
5510 if (bfa_fcport_is_pbcdisabled(bfa)) {
5511 bfa_trc(fcdiag, BFA_STATUS_PBC);
5512 return BFA_STATUS_PBC;
5513 }
5514
5515 if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
5516 bfa_trc(fcdiag, opmode);
5517 return BFA_STATUS_PORT_NOT_DISABLED;
5518 }
5519
5520 /* Check if the speed is supported */
5521 bfa_fcport_get_attr(bfa, &attr);
5522 bfa_trc(fcdiag, attr.speed_supported);
5523 if (speed > attr.speed_supported)
5524 return BFA_STATUS_UNSUPP_SPEED;
5525
5526 /* For Mezz card, port speed entered needs to be checked */
5527 if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
5528 if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5529 if ((speed == BFA_PORT_SPEED_1GBPS) &&
5530 (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
5531 return BFA_STATUS_UNSUPP_SPEED;
5532 if (!(speed == BFA_PORT_SPEED_1GBPS ||
5533 speed == BFA_PORT_SPEED_2GBPS ||
5534 speed == BFA_PORT_SPEED_4GBPS ||
5535 speed == BFA_PORT_SPEED_8GBPS ||
5536 speed == BFA_PORT_SPEED_16GBPS ||
5537 speed == BFA_PORT_SPEED_AUTO))
5538 return BFA_STATUS_UNSUPP_SPEED;
5539 } else {
5540 if (speed != BFA_PORT_SPEED_10GBPS)
5541 return BFA_STATUS_UNSUPP_SPEED;
5542 }
5543 }
5544
5545 /* check to see if there is another destructive diag cmd running */
5546 if (fcdiag->lb.lock) {
5547 bfa_trc(fcdiag, fcdiag->lb.lock);
5548 return BFA_STATUS_DEVBUSY;
5549 }
5550
5551 fcdiag->lb.lock = 1;
5552 loopback.lb_mode = opmode;
5553 loopback.speed = speed;
5554 loopback.loopcnt = lpcnt;
5555 loopback.pattern = pat;
5556 fcdiag->lb.result = result;
5557 fcdiag->lb.cbfn = cbfn;
5558 fcdiag->lb.cbarg = cbarg;
5559 memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
5560 bfa_fcdiag_set_busy_status(fcdiag);
5561
5562 /* Send msg to fw */
5563 status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
5564 return status;
5565}
5566
5567/*
5568 * DIAG queue test command
5569 *
5570 * @param[in] *bfa - bfa data struct
5571 * @param[in] force - 1: don't do ioc op checking
5572 * @param[in] queue - queue no. to test
5573 * @param[in] *result - pt to bfa_diag_qtest_result_t data struct
5574 * @param[in] cbfn - callback function
5575 * @param[in] *cbarg - callback functioin arg
5576 *
5577 * @param[out]
5578 */
5579bfa_status_t
5580bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
5581 struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
5582 void *cbarg)
5583{
5584 struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5585 bfa_status_t status;
5586 bfa_trc(fcdiag, force);
5587 bfa_trc(fcdiag, queue);
5588
5589 if (!force && !bfa_iocfc_is_operational(bfa))
5590 return BFA_STATUS_IOC_NON_OP;
5591
5592 /* check to see if there is another destructive diag cmd running */
5593 if (fcdiag->qtest.lock) {
5594 bfa_trc(fcdiag, fcdiag->qtest.lock);
5595 return BFA_STATUS_DEVBUSY;
5596 }
5597
5598 /* Initialization */
5599 fcdiag->qtest.lock = 1;
5600 fcdiag->qtest.cbfn = cbfn;
5601 fcdiag->qtest.cbarg = cbarg;
5602 fcdiag->qtest.result = result;
5603 fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5604
5605 /* Init test results */
5606 fcdiag->qtest.result->status = BFA_STATUS_OK;
5607 fcdiag->qtest.result->count = 0;
5608
5609 /* send */
5610 if (queue < BFI_IOC_MAX_CQS) {
5611 fcdiag->qtest.result->queue = (u8)queue;
5612 fcdiag->qtest.queue = (u8)queue;
5613 fcdiag->qtest.all = 0;
5614 } else {
5615 fcdiag->qtest.result->queue = 0;
5616 fcdiag->qtest.queue = 0;
5617 fcdiag->qtest.all = 1;
5618 }
5619 status = bfa_fcdiag_queuetest_send(fcdiag);
5620
5621 /* Start a timer */
5622 if (status == BFA_STATUS_OK) {
5623 bfa_timer_start(bfa, &fcdiag->qtest.timer,
5624 bfa_fcdiag_queuetest_timeout, fcdiag,
5625 BFA_DIAG_QTEST_TOV);
5626 fcdiag->qtest.timer_active = 1;
5627 }
5628 return status;
5629}
5630
5631/*
5632 * DIAG PLB is running
5633 *
5634 * @param[in] *bfa - bfa data struct
5635 *
5636 * @param[out]
5637 */
5638bfa_status_t
5639bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
5640{
5641 struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5642 return fcdiag->lb.lock ? BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
5643}
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index 4c0ac3e1a137..fbe513a671b5 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -548,6 +548,8 @@ enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
548 548
549void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn); 549void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit, u8 bb_scn);
550bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa); 550bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa);
551void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
552 bfa_boolean_t link_e2e_beacon);
551bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); 553bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa);
552bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, 554bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
553 union bfa_fcport_stats_u *stats, 555 union bfa_fcport_stats_u *stats,
@@ -662,4 +664,49 @@ bfa_status_t bfa_faa_disable(struct bfa_s *bfa,
662bfa_status_t bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr, 664bfa_status_t bfa_faa_query(struct bfa_s *bfa, struct bfa_faa_attr_s *attr,
663 bfa_cb_iocfc_t cbfn, void *cbarg); 665 bfa_cb_iocfc_t cbfn, void *cbarg);
664 666
667/*
668 * FC DIAG data structure
669 */
670struct bfa_fcdiag_qtest_s {
671 struct bfa_diag_qtest_result_s *result;
672 bfa_cb_diag_t cbfn;
673 void *cbarg;
674 struct bfa_timer_s timer;
675 u32 status;
676 u32 count;
677 u8 lock;
678 u8 queue;
679 u8 all;
680 u8 timer_active;
681};
682
683struct bfa_fcdiag_lb_s {
684 bfa_cb_diag_t cbfn;
685 void *cbarg;
686 void *result;
687 bfa_boolean_t lock;
688 u32 status;
689};
690
691struct bfa_fcdiag_s {
692 struct bfa_s *bfa; /* Back pointer to BFA */
693 struct bfa_trc_mod_s *trcmod;
694 struct bfa_fcdiag_lb_s lb;
695 struct bfa_fcdiag_qtest_s qtest;
696};
697
698#define BFA_FCDIAG_MOD(__bfa) (&(__bfa)->modules.fcdiag)
699
700void bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg);
701
702bfa_status_t bfa_fcdiag_loopback(struct bfa_s *bfa,
703 enum bfa_port_opmode opmode,
704 enum bfa_port_speed speed, u32 lpcnt, u32 pat,
705 struct bfa_diag_loopback_result_s *result,
706 bfa_cb_diag_t cbfn, void *cbarg);
707bfa_status_t bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 ignore,
708 u32 queue, struct bfa_diag_qtest_result_s *result,
709 bfa_cb_diag_t cbfn, void *cbarg);
710bfa_status_t bfa_fcdiag_lb_is_running(struct bfa_s *bfa);
711
665#endif /* __BFA_SVC_H__ */ 712#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 5444661f1150..a60270287064 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -1214,6 +1214,185 @@ out:
1214 return 0; 1214 return 0;
1215} 1215}
1216 1216
1217int
1218bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd)
1219{
1220 struct bfa_bsg_diag_get_temp_s *iocmd =
1221 (struct bfa_bsg_diag_get_temp_s *)cmd;
1222 struct bfad_hal_comp fcomp;
1223 unsigned long flags;
1224
1225 init_completion(&fcomp.comp);
1226 spin_lock_irqsave(&bfad->bfad_lock, flags);
1227 iocmd->status = bfa_diag_tsensor_query(BFA_DIAG_MOD(&bfad->bfa),
1228 &iocmd->result, bfad_hcb_comp, &fcomp);
1229 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1230 bfa_trc(bfad, iocmd->status);
1231 if (iocmd->status != BFA_STATUS_OK)
1232 goto out;
1233 wait_for_completion(&fcomp.comp);
1234 iocmd->status = fcomp.status;
1235out:
1236 return 0;
1237}
1238
1239int
1240bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd)
1241{
1242 struct bfa_bsg_diag_memtest_s *iocmd =
1243 (struct bfa_bsg_diag_memtest_s *)cmd;
1244 struct bfad_hal_comp fcomp;
1245 unsigned long flags;
1246
1247 init_completion(&fcomp.comp);
1248 spin_lock_irqsave(&bfad->bfad_lock, flags);
1249 iocmd->status = bfa_diag_memtest(BFA_DIAG_MOD(&bfad->bfa),
1250 &iocmd->memtest, iocmd->pat,
1251 &iocmd->result, bfad_hcb_comp, &fcomp);
1252 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1253 bfa_trc(bfad, iocmd->status);
1254 if (iocmd->status != BFA_STATUS_OK)
1255 goto out;
1256 wait_for_completion(&fcomp.comp);
1257 iocmd->status = fcomp.status;
1258out:
1259 return 0;
1260}
1261
1262int
1263bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd)
1264{
1265 struct bfa_bsg_diag_loopback_s *iocmd =
1266 (struct bfa_bsg_diag_loopback_s *)cmd;
1267 struct bfad_hal_comp fcomp;
1268 unsigned long flags;
1269
1270 init_completion(&fcomp.comp);
1271 spin_lock_irqsave(&bfad->bfad_lock, flags);
1272 iocmd->status = bfa_fcdiag_loopback(&bfad->bfa, iocmd->opmode,
1273 iocmd->speed, iocmd->lpcnt, iocmd->pat,
1274 &iocmd->result, bfad_hcb_comp, &fcomp);
1275 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1276 bfa_trc(bfad, iocmd->status);
1277 if (iocmd->status != BFA_STATUS_OK)
1278 goto out;
1279 wait_for_completion(&fcomp.comp);
1280 iocmd->status = fcomp.status;
1281out:
1282 return 0;
1283}
1284
1285int
1286bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd)
1287{
1288 struct bfa_bsg_diag_fwping_s *iocmd =
1289 (struct bfa_bsg_diag_fwping_s *)cmd;
1290 struct bfad_hal_comp fcomp;
1291 unsigned long flags;
1292
1293 init_completion(&fcomp.comp);
1294 spin_lock_irqsave(&bfad->bfad_lock, flags);
1295 iocmd->status = bfa_diag_fwping(BFA_DIAG_MOD(&bfad->bfa), iocmd->cnt,
1296 iocmd->pattern, &iocmd->result,
1297 bfad_hcb_comp, &fcomp);
1298 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1299 bfa_trc(bfad, iocmd->status);
1300 if (iocmd->status != BFA_STATUS_OK)
1301 goto out;
1302 bfa_trc(bfad, 0x77771);
1303 wait_for_completion(&fcomp.comp);
1304 iocmd->status = fcomp.status;
1305out:
1306 return 0;
1307}
1308
1309int
1310bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd)
1311{
1312 struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd;
1313 struct bfad_hal_comp fcomp;
1314 unsigned long flags;
1315
1316 init_completion(&fcomp.comp);
1317 spin_lock_irqsave(&bfad->bfad_lock, flags);
1318 iocmd->status = bfa_fcdiag_queuetest(&bfad->bfa, iocmd->force,
1319 iocmd->queue, &iocmd->result,
1320 bfad_hcb_comp, &fcomp);
1321 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1322 if (iocmd->status != BFA_STATUS_OK)
1323 goto out;
1324 wait_for_completion(&fcomp.comp);
1325 iocmd->status = fcomp.status;
1326out:
1327 return 0;
1328}
1329
1330int
1331bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd)
1332{
1333 struct bfa_bsg_sfp_show_s *iocmd =
1334 (struct bfa_bsg_sfp_show_s *)cmd;
1335 struct bfad_hal_comp fcomp;
1336 unsigned long flags;
1337
1338 init_completion(&fcomp.comp);
1339 spin_lock_irqsave(&bfad->bfad_lock, flags);
1340 iocmd->status = bfa_sfp_show(BFA_SFP_MOD(&bfad->bfa), &iocmd->sfp,
1341 bfad_hcb_comp, &fcomp);
1342 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1343 bfa_trc(bfad, iocmd->status);
1344 if (iocmd->status != BFA_STATUS_OK)
1345 goto out;
1346 wait_for_completion(&fcomp.comp);
1347 iocmd->status = fcomp.status;
1348 bfa_trc(bfad, iocmd->status);
1349out:
1350 return 0;
1351}
1352
1353int
1354bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd)
1355{
1356 struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd;
1357 unsigned long flags;
1358
1359 spin_lock_irqsave(&bfad->bfad_lock, flags);
1360 iocmd->status = bfa_diag_ledtest(BFA_DIAG_MOD(&bfad->bfa),
1361 &iocmd->ledtest);
1362 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1363 return 0;
1364}
1365
1366int
1367bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd)
1368{
1369 struct bfa_bsg_diag_beacon_s *iocmd =
1370 (struct bfa_bsg_diag_beacon_s *)cmd;
1371 unsigned long flags;
1372
1373 spin_lock_irqsave(&bfad->bfad_lock, flags);
1374 iocmd->status = bfa_diag_beacon_port(BFA_DIAG_MOD(&bfad->bfa),
1375 iocmd->beacon, iocmd->link_e2e_beacon,
1376 iocmd->second);
1377 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1378 return 0;
1379}
1380
1381int
1382bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
1383{
1384 struct bfa_bsg_diag_lb_stat_s *iocmd =
1385 (struct bfa_bsg_diag_lb_stat_s *)cmd;
1386 unsigned long flags;
1387
1388 spin_lock_irqsave(&bfad->bfad_lock, flags);
1389 iocmd->status = bfa_fcdiag_lb_is_running(&bfad->bfa);
1390 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
1391 bfa_trc(bfad, iocmd->status);
1392
1393 return 0;
1394}
1395
1217static int 1396static int
1218bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, 1397bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
1219 unsigned int payload_len) 1398 unsigned int payload_len)
@@ -1360,6 +1539,33 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
1360 case IOCMD_FLASH_READ_PART: 1539 case IOCMD_FLASH_READ_PART:
1361 rc = bfad_iocmd_flash_read_part(bfad, iocmd, payload_len); 1540 rc = bfad_iocmd_flash_read_part(bfad, iocmd, payload_len);
1362 break; 1541 break;
1542 case IOCMD_DIAG_TEMP:
1543 rc = bfad_iocmd_diag_temp(bfad, iocmd);
1544 break;
1545 case IOCMD_DIAG_MEMTEST:
1546 rc = bfad_iocmd_diag_memtest(bfad, iocmd);
1547 break;
1548 case IOCMD_DIAG_LOOPBACK:
1549 rc = bfad_iocmd_diag_loopback(bfad, iocmd);
1550 break;
1551 case IOCMD_DIAG_FWPING:
1552 rc = bfad_iocmd_diag_fwping(bfad, iocmd);
1553 break;
1554 case IOCMD_DIAG_QUEUETEST:
1555 rc = bfad_iocmd_diag_queuetest(bfad, iocmd);
1556 break;
1557 case IOCMD_DIAG_SFP:
1558 rc = bfad_iocmd_diag_sfp(bfad, iocmd);
1559 break;
1560 case IOCMD_DIAG_LED:
1561 rc = bfad_iocmd_diag_led(bfad, iocmd);
1562 break;
1563 case IOCMD_DIAG_BEACON_LPORT:
1564 rc = bfad_iocmd_diag_beacon_lport(bfad, iocmd);
1565 break;
1566 case IOCMD_DIAG_LB_STAT:
1567 rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
1568 break;
1363 default: 1569 default:
1364 rc = EINVAL; 1570 rc = EINVAL;
1365 break; 1571 break;
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 6bece6c1d876..89942773febe 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -71,6 +71,15 @@ enum {
71 IOCMD_FLASH_ERASE_PART, 71 IOCMD_FLASH_ERASE_PART,
72 IOCMD_FLASH_UPDATE_PART, 72 IOCMD_FLASH_UPDATE_PART,
73 IOCMD_FLASH_READ_PART, 73 IOCMD_FLASH_READ_PART,
74 IOCMD_DIAG_TEMP,
75 IOCMD_DIAG_MEMTEST,
76 IOCMD_DIAG_LOOPBACK,
77 IOCMD_DIAG_FWPING,
78 IOCMD_DIAG_QUEUETEST,
79 IOCMD_DIAG_SFP,
80 IOCMD_DIAG_LED,
81 IOCMD_DIAG_BEACON_LPORT,
82 IOCMD_DIAG_LB_STAT,
74}; 83};
75 84
76struct bfa_bsg_gen_s { 85struct bfa_bsg_gen_s {
@@ -357,6 +366,80 @@ struct bfa_bsg_flash_s {
357 u64 buf_ptr; 366 u64 buf_ptr;
358}; 367};
359 368
369struct bfa_bsg_diag_get_temp_s {
370 bfa_status_t status;
371 u16 bfad_num;
372 u16 rsvd;
373 struct bfa_diag_results_tempsensor_s result;
374};
375
376struct bfa_bsg_diag_memtest_s {
377 bfa_status_t status;
378 u16 bfad_num;
379 u16 rsvd[3];
380 u32 pat;
381 struct bfa_diag_memtest_result result;
382 struct bfa_diag_memtest_s memtest;
383};
384
385struct bfa_bsg_diag_loopback_s {
386 bfa_status_t status;
387 u16 bfad_num;
388 u16 rsvd;
389 enum bfa_port_opmode opmode;
390 enum bfa_port_speed speed;
391 u32 lpcnt;
392 u32 pat;
393 struct bfa_diag_loopback_result_s result;
394};
395
396struct bfa_bsg_diag_fwping_s {
397 bfa_status_t status;
398 u16 bfad_num;
399 u16 rsvd;
400 u32 cnt;
401 u32 pattern;
402 struct bfa_diag_results_fwping result;
403};
404
405struct bfa_bsg_diag_qtest_s {
406 bfa_status_t status;
407 u16 bfad_num;
408 u16 rsvd;
409 u32 force;
410 u32 queue;
411 struct bfa_diag_qtest_result_s result;
412};
413
414struct bfa_bsg_sfp_show_s {
415 bfa_status_t status;
416 u16 bfad_num;
417 u16 rsvd;
418 struct sfp_mem_s sfp;
419};
420
421struct bfa_bsg_diag_led_s {
422 bfa_status_t status;
423 u16 bfad_num;
424 u16 rsvd;
425 struct bfa_diag_ledtest_s ledtest;
426};
427
428struct bfa_bsg_diag_beacon_s {
429 bfa_status_t status;
430 u16 bfad_num;
431 u16 rsvd;
432 bfa_boolean_t beacon;
433 bfa_boolean_t link_e2e_beacon;
434 u32 second;
435};
436
437struct bfa_bsg_diag_lb_stat_s {
438 bfa_status_t status;
439 u16 bfad_num;
440 u16 rsvd;
441};
442
360struct bfa_bsg_fcpt_s { 443struct bfa_bsg_fcpt_s {
361 bfa_status_t status; 444 bfa_status_t status;
362 u16 vf_id; 445 u16 vf_id;
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 48be0c54f2de..b412e0300dd4 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -214,10 +214,10 @@ bfad_debugfs_read(struct file *file, char __user *buf,
214 214
215#define BFA_REG_CT_ADDRSZ (0x40000) 215#define BFA_REG_CT_ADDRSZ (0x40000)
216#define BFA_REG_CB_ADDRSZ (0x20000) 216#define BFA_REG_CB_ADDRSZ (0x20000)
217#define BFA_REG_ADDRSZ(__bfa) \ 217#define BFA_REG_ADDRSZ(__ioc) \
218 ((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ? \ 218 ((u32)(bfa_asic_id_ctc(bfa_ioc_devid(__ioc)) ? \
219 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ) 219 BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ))
220#define BFA_REG_ADDRMSK(__bfa) ((u32)(BFA_REG_ADDRSZ(__bfa) - 1)) 220#define BFA_REG_ADDRMSK(__ioc) (BFA_REG_ADDRSZ(__ioc) - 1)
221 221
222static bfa_status_t 222static bfa_status_t
223bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len) 223bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
@@ -236,7 +236,7 @@ bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
236 return BFA_STATUS_EINVAL; 236 return BFA_STATUS_EINVAL;
237 } else { 237 } else {
238 /* CB register space 64KB */ 238 /* CB register space 64KB */
239 if ((offset + (len<<2)) > BFA_REG_ADDRMSK(bfa)) 239 if ((offset + (len<<2)) > BFA_REG_ADDRMSK(&bfa->ioc))
240 return BFA_STATUS_EINVAL; 240 return BFA_STATUS_EINVAL;
241 } 241 }
242 return BFA_STATUS_OK; 242 return BFA_STATUS_OK;
@@ -317,7 +317,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
317 317
318 bfad->reglen = len << 2; 318 bfad->reglen = len << 2;
319 rb = bfa_ioc_bar0(ioc); 319 rb = bfa_ioc_bar0(ioc);
320 addr &= BFA_REG_ADDRMSK(bfa); 320 addr &= BFA_REG_ADDRMSK(ioc);
321 321
322 /* offset and len sanity check */ 322 /* offset and len sanity check */
323 rc = bfad_reg_offset_check(bfa, addr, len); 323 rc = bfad_reg_offset_check(bfa, addr, len);
@@ -380,7 +380,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
380 } 380 }
381 kfree(kern_buf); 381 kfree(kern_buf);
382 382
383 addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */ 383 addr &= BFA_REG_ADDRMSK(ioc); /* offset only 17 bit and word align */
384 384
385 /* offset and len sanity check */ 385 /* offset and len sanity check */
386 rc = bfad_reg_offset_check(bfa, addr, 1); 386 rc = bfad_reg_offset_check(bfa, addr, 1);
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index b7eb3dc27d5b..efa41b64bb32 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -190,6 +190,7 @@ enum bfi_pcifn_class {
190 */ 190 */
191enum bfi_mclass { 191enum bfi_mclass {
192 BFI_MC_IOC = 1, /* IO Controller (IOC) */ 192 BFI_MC_IOC = 1, /* IO Controller (IOC) */
193 BFI_MC_DIAG = 2, /* Diagnostic Msgs */
193 BFI_MC_FLASH = 3, /* Flash message class */ 194 BFI_MC_FLASH = 3, /* Flash message class */
194 BFI_MC_CEE = 4, /* CEE */ 195 BFI_MC_CEE = 4, /* CEE */
195 BFI_MC_FCPORT = 5, /* FC port */ 196 BFI_MC_FCPORT = 5, /* FC port */
@@ -339,7 +340,7 @@ struct bfi_ioc_image_hdr_s {
339 ((u32)(__p1_mode))) 340 ((u32)(__p1_mode)))
340 341
341#define BFI_FWBOOT_TYPE_NORMAL 0 342#define BFI_FWBOOT_TYPE_NORMAL 0
342#define BFI_FWBOOT_TYPE_MEMTEST 1 343#define BFI_FWBOOT_TYPE_MEMTEST 2
343#define BFI_FWBOOT_ENV_OS 0 344#define BFI_FWBOOT_ENV_OS 0
344 345
345enum bfi_port_mode { 346enum bfi_port_mode {
@@ -923,6 +924,112 @@ struct bfi_flash_erase_rsp_s {
923 u32 status; 924 u32 status;
924}; 925};
925 926
927/*
928 *----------------------------------------------------------------------
929 * DIAG
930 *----------------------------------------------------------------------
931 */
932enum bfi_diag_h2i {
933 BFI_DIAG_H2I_PORTBEACON = 1,
934 BFI_DIAG_H2I_LOOPBACK = 2,
935 BFI_DIAG_H2I_FWPING = 3,
936 BFI_DIAG_H2I_TEMPSENSOR = 4,
937 BFI_DIAG_H2I_LEDTEST = 5,
938 BFI_DIAG_H2I_QTEST = 6,
939};
940
941enum bfi_diag_i2h {
942 BFI_DIAG_I2H_PORTBEACON = BFA_I2HM(BFI_DIAG_H2I_PORTBEACON),
943 BFI_DIAG_I2H_LOOPBACK = BFA_I2HM(BFI_DIAG_H2I_LOOPBACK),
944 BFI_DIAG_I2H_FWPING = BFA_I2HM(BFI_DIAG_H2I_FWPING),
945 BFI_DIAG_I2H_TEMPSENSOR = BFA_I2HM(BFI_DIAG_H2I_TEMPSENSOR),
946 BFI_DIAG_I2H_LEDTEST = BFA_I2HM(BFI_DIAG_H2I_LEDTEST),
947 BFI_DIAG_I2H_QTEST = BFA_I2HM(BFI_DIAG_H2I_QTEST),
948};
949
950#define BFI_DIAG_MAX_SGES 2
951#define BFI_DIAG_DMA_BUF_SZ (2 * 1024)
952#define BFI_BOOT_MEMTEST_RES_ADDR 0x900
953#define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3
954
955struct bfi_diag_lb_req_s {
956 struct bfi_mhdr_s mh;
957 u32 loopcnt;
958 u32 pattern;
959 u8 lb_mode; /*!< bfa_port_opmode_t */
960 u8 speed; /*!< bfa_port_speed_t */
961 u8 rsvd[2];
962};
963
964struct bfi_diag_lb_rsp_s {
965 struct bfi_mhdr_s mh; /* 4 bytes */
966 struct bfa_diag_loopback_result_s res; /* 16 bytes */
967};
968
969struct bfi_diag_fwping_req_s {
970 struct bfi_mhdr_s mh; /* 4 bytes */
971 struct bfi_alen_s alen; /* 12 bytes */
972 u32 data; /* user input data pattern */
973 u32 count; /* user input dma count */
974 u8 qtag; /* track CPE vc */
975 u8 rsv[3];
976};
977
978struct bfi_diag_fwping_rsp_s {
979 struct bfi_mhdr_s mh; /* 4 bytes */
980 u32 data; /* user input data pattern */
981 u8 qtag; /* track CPE vc */
982 u8 dma_status; /* dma status */
983 u8 rsv[2];
984};
985
986/*
987 * Temperature Sensor
988 */
989struct bfi_diag_ts_req_s {
990 struct bfi_mhdr_s mh; /* 4 bytes */
991 u16 temp; /* 10-bit A/D value */
992 u16 brd_temp; /* 9-bit board temp */
993 u8 status;
994 u8 ts_junc; /* show junction tempsensor */
995 u8 ts_brd; /* show board tempsensor */
996 u8 rsv;
997};
998#define bfi_diag_ts_rsp_t struct bfi_diag_ts_req_s
999
1000struct bfi_diag_ledtest_req_s {
1001 struct bfi_mhdr_s mh; /* 4 bytes */
1002 u8 cmd;
1003 u8 color;
1004 u8 portid;
1005 u8 led; /* bitmap of LEDs to be tested */
1006 u16 freq; /* no. of blinks every 10 secs */
1007 u8 rsv[2];
1008};
1009
1010/* notify host led operation is done */
1011struct bfi_diag_ledtest_rsp_s {
1012 struct bfi_mhdr_s mh; /* 4 bytes */
1013};
1014
1015struct bfi_diag_portbeacon_req_s {
1016 struct bfi_mhdr_s mh; /* 4 bytes */
1017 u32 period; /* beaconing period */
1018 u8 beacon; /* 1: beacon on */
1019 u8 rsvd[3];
1020};
1021
1022/* notify host the beacon is off */
1023struct bfi_diag_portbeacon_rsp_s {
1024 struct bfi_mhdr_s mh; /* 4 bytes */
1025};
1026
1027struct bfi_diag_qtest_req_s {
1028 struct bfi_mhdr_s mh; /* 4 bytes */
1029 u32 data[BFI_LMSG_PL_WSZ]; /* fill up tcm prefetch area */
1030};
1031#define bfi_diag_qtest_rsp_t struct bfi_diag_qtest_req_s
1032
926#pragma pack() 1033#pragma pack()
927 1034
928#endif /* __BFI_H__ */ 1035#endif /* __BFI_H__ */