aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <james.smart@avagotech.com>2015-05-21 13:55:21 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-06-06 01:34:55 -0400
commit86478875eb4d2e7108b914f8a5e53be260816d5c (patch)
tree9f97de6ec770e84e276bfd83d147243ec1428477 /drivers/scsi
parenta1efe163102fed8a3b5990a67cadb1193e630820 (diff)
lpfc: Add support for RDP ELS command.
Signed-off-by: Dick Kennedy <dick.kennedy@avagotech.com> Signed-off-by: James Smart <james.smart@avagotech.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c420
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h169
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h201
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c152
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h10
7 files changed, 955 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3246d09d22ff..a5a56fa31e70 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -231,6 +231,7 @@ struct lpfc_stats {
231 uint32_t elsRcvRTV; 231 uint32_t elsRcvRTV;
232 uint32_t elsRcvECHO; 232 uint32_t elsRcvECHO;
233 uint32_t elsRcvLCB; 233 uint32_t elsRcvLCB;
234 uint32_t elsRcvRDP;
234 uint32_t elsXmitFLOGI; 235 uint32_t elsXmitFLOGI;
235 uint32_t elsXmitFDISC; 236 uint32_t elsXmitFDISC;
236 uint32_t elsXmitPLOGI; 237 uint32_t elsXmitPLOGI;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 587e3e962f2b..b0e6fe46448d 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -498,3 +498,5 @@ bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
498bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *, 498bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *,
499 struct lpfc_name *, uint64_t *, struct lpfc_name *, 499 struct lpfc_name *, uint64_t *, struct lpfc_name *,
500 struct lpfc_name *, uint64_t *, uint32_t *); 500 struct lpfc_name *, uint64_t *, uint32_t *);
501int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox);
502void lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb);
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 3975276d1155..724b61c7ae9e 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -4615,6 +4615,422 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
4615 return sentplogi; 4615 return sentplogi;
4616} 4616}
4617 4617
4618void
4619lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc,
4620 uint32_t word0)
4621{
4622
4623 desc->tag = cpu_to_be32(RDP_LINK_SERVICE_DESC_TAG);
4624 desc->payload.els_req = word0;
4625 desc->length = cpu_to_be32(sizeof(desc->payload));
4626}
4627
4628void
4629lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc,
4630 uint8_t *page_a0, uint8_t *page_a2)
4631{
4632 uint16_t wavelength;
4633 uint16_t temperature;
4634 uint16_t rx_power;
4635 uint16_t tx_bias;
4636 uint16_t tx_power;
4637 uint16_t vcc;
4638 uint16_t flag = 0;
4639 struct sff_trasnceiver_codes_byte4 *trasn_code_byte4;
4640 struct sff_trasnceiver_codes_byte5 *trasn_code_byte5;
4641
4642 desc->tag = cpu_to_be32(RDP_SFP_DESC_TAG);
4643
4644 trasn_code_byte4 = (struct sff_trasnceiver_codes_byte4 *)
4645 &page_a0[SSF_TRANSCEIVER_CODE_B4];
4646 trasn_code_byte5 = (struct sff_trasnceiver_codes_byte5 *)
4647 &page_a0[SSF_TRANSCEIVER_CODE_B5];
4648
4649 if ((trasn_code_byte4->fc_sw_laser) ||
4650 (trasn_code_byte5->fc_sw_laser_sl) ||
4651 (trasn_code_byte5->fc_sw_laser_sn)) { /* check if its short WL */
4652 flag |= (SFP_FLAG_PT_SWLASER << SFP_FLAG_PT_SHIFT);
4653 } else if (trasn_code_byte4->fc_lw_laser) {
4654 wavelength = (page_a0[SSF_WAVELENGTH_B1] << 8) |
4655 page_a0[SSF_WAVELENGTH_B0];
4656 if (wavelength == SFP_WAVELENGTH_LC1310)
4657 flag |= SFP_FLAG_PT_LWLASER_LC1310 << SFP_FLAG_PT_SHIFT;
4658 if (wavelength == SFP_WAVELENGTH_LL1550)
4659 flag |= SFP_FLAG_PT_LWLASER_LL1550 << SFP_FLAG_PT_SHIFT;
4660 }
4661 /* check if its SFP+ */
4662 flag |= ((page_a0[SSF_IDENTIFIER] == SFF_PG0_IDENT_SFP) ?
4663 SFP_FLAG_CT_SFP_PLUS : SFP_FLAG_CT_UNKNOWN)
4664 << SFP_FLAG_CT_SHIFT;
4665
4666 /* check if its OPTICAL */
4667 flag |= ((page_a0[SSF_CONNECTOR] == SFF_PG0_CONNECTOR_LC) ?
4668 SFP_FLAG_IS_OPTICAL_PORT : 0)
4669 << SFP_FLAG_IS_OPTICAL_SHIFT;
4670
4671 temperature = (page_a2[SFF_TEMPERATURE_B1] << 8 |
4672 page_a2[SFF_TEMPERATURE_B0]);
4673 vcc = (page_a2[SFF_VCC_B1] << 8 |
4674 page_a2[SFF_VCC_B0]);
4675 tx_power = (page_a2[SFF_TXPOWER_B1] << 8 |
4676 page_a2[SFF_TXPOWER_B0]);
4677 tx_bias = (page_a2[SFF_TX_BIAS_CURRENT_B1] << 8 |
4678 page_a2[SFF_TX_BIAS_CURRENT_B0]);
4679 rx_power = (page_a2[SFF_RXPOWER_B1] << 8 |
4680 page_a2[SFF_RXPOWER_B0]);
4681 desc->sfp_info.temperature = cpu_to_be16(temperature);
4682 desc->sfp_info.rx_power = cpu_to_be16(rx_power);
4683 desc->sfp_info.tx_bias = cpu_to_be16(tx_bias);
4684 desc->sfp_info.tx_power = cpu_to_be16(tx_power);
4685 desc->sfp_info.vcc = cpu_to_be16(vcc);
4686
4687 desc->sfp_info.flags = cpu_to_be16(flag);
4688 desc->length = cpu_to_be32(sizeof(desc->sfp_info));
4689}
4690
4691void
4692lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc,
4693 READ_LNK_VAR *stat)
4694{
4695 uint32_t type;
4696
4697 desc->tag = cpu_to_be32(RDP_LINK_ERROR_STATUS_DESC_TAG);
4698
4699 type = VN_PT_PHY_PF_PORT << VN_PT_PHY_SHIFT;
4700
4701 desc->info.port_type = cpu_to_be32(type);
4702
4703 desc->info.link_status.link_failure_cnt =
4704 cpu_to_be32(stat->linkFailureCnt);
4705 desc->info.link_status.loss_of_synch_cnt =
4706 cpu_to_be32(stat->lossSyncCnt);
4707 desc->info.link_status.loss_of_signal_cnt =
4708 cpu_to_be32(stat->lossSignalCnt);
4709 desc->info.link_status.primitive_seq_proto_err =
4710 cpu_to_be32(stat->primSeqErrCnt);
4711 desc->info.link_status.invalid_trans_word =
4712 cpu_to_be32(stat->invalidXmitWord);
4713 desc->info.link_status.invalid_crc_cnt = cpu_to_be32(stat->crcCnt);
4714
4715 desc->length = cpu_to_be32(sizeof(desc->info));
4716}
4717
4718void
4719lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
4720{
4721 uint16_t rdp_cap = 0;
4722 uint16_t rdp_speed;
4723
4724 desc->tag = cpu_to_be32(RDP_PORT_SPEED_DESC_TAG);
4725
4726 switch (phba->sli4_hba.link_state.speed) {
4727 case LPFC_FC_LA_SPEED_1G:
4728 rdp_speed = RDP_PS_1GB;
4729 break;
4730 case LPFC_FC_LA_SPEED_2G:
4731 rdp_speed = RDP_PS_2GB;
4732 break;
4733 case LPFC_FC_LA_SPEED_4G:
4734 rdp_speed = RDP_PS_4GB;
4735 break;
4736 case LPFC_FC_LA_SPEED_8G:
4737 rdp_speed = RDP_PS_8GB;
4738 break;
4739 case LPFC_FC_LA_SPEED_10G:
4740 rdp_speed = RDP_PS_10GB;
4741 break;
4742 case LPFC_FC_LA_SPEED_16G:
4743 rdp_speed = RDP_PS_16GB;
4744 break;
4745 case LPFC_FC_LA_SPEED_32G:
4746 rdp_speed = RDP_PS_32GB;
4747 break;
4748 default:
4749 rdp_speed = RDP_PS_UNKNOWN;
4750 break;
4751 }
4752
4753 desc->info.port_speed.speed = cpu_to_be16(rdp_speed);
4754
4755 if (phba->lmt & LMT_16Gb)
4756 rdp_cap |= RDP_PS_16GB;
4757 if (phba->lmt & LMT_10Gb)
4758 rdp_cap |= RDP_PS_10GB;
4759 if (phba->lmt & LMT_8Gb)
4760 rdp_cap |= RDP_PS_8GB;
4761 if (phba->lmt & LMT_4Gb)
4762 rdp_cap |= RDP_PS_4GB;
4763 if (phba->lmt & LMT_2Gb)
4764 rdp_cap |= RDP_PS_2GB;
4765 if (phba->lmt & LMT_1Gb)
4766 rdp_cap |= RDP_PS_1GB;
4767
4768 if (rdp_cap == 0)
4769 rdp_cap = RDP_CAP_UNKNOWN;
4770
4771 desc->info.port_speed.capabilities = cpu_to_be16(rdp_cap);
4772 desc->length = cpu_to_be32(sizeof(desc->info));
4773}
4774
4775void
4776lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc,
4777 struct lpfc_hba *phba)
4778{
4779
4780 desc->tag = cpu_to_be32(RDP_PORT_NAMES_DESC_TAG);
4781
4782 memcpy(desc->port_names.wwnn, phba->wwnn,
4783 sizeof(desc->port_names.wwnn));
4784
4785 memcpy(desc->port_names.wwpn, &phba->wwpn,
4786 sizeof(desc->port_names.wwpn));
4787
4788 desc->length = cpu_to_be32(sizeof(desc->port_names));
4789}
4790
4791void
4792lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc,
4793 struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
4794{
4795
4796 desc->tag = cpu_to_be32(RDP_PORT_NAMES_DESC_TAG);
4797 if (vport->fc_flag & FC_FABRIC) {
4798 memcpy(desc->port_names.wwnn, &vport->fabric_nodename,
4799 sizeof(desc->port_names.wwnn));
4800
4801 memcpy(desc->port_names.wwpn, &vport->fabric_portname,
4802 sizeof(desc->port_names.wwpn));
4803 } else { /* Point to Point */
4804 memcpy(desc->port_names.wwnn, &ndlp->nlp_nodename,
4805 sizeof(desc->port_names.wwnn));
4806
4807 memcpy(desc->port_names.wwnn, &ndlp->nlp_portname,
4808 sizeof(desc->port_names.wwpn));
4809 }
4810
4811 desc->length = cpu_to_be32(sizeof(desc->port_names));
4812}
4813
4814void
4815lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
4816 int status)
4817{
4818 struct lpfc_nodelist *ndlp = rdp_context->ndlp;
4819 struct lpfc_vport *vport = ndlp->vport;
4820 struct lpfc_iocbq *elsiocb;
4821 IOCB_t *icmd;
4822 uint8_t *pcmd;
4823 struct ls_rjt *stat;
4824 struct fc_rdp_res_frame *rdp_res;
4825 uint32_t cmdsize;
4826 int rc;
4827
4828 if (status != SUCCESS)
4829 goto error;
4830 cmdsize = sizeof(struct fc_rdp_res_frame);
4831
4832 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize,
4833 lpfc_max_els_tries, rdp_context->ndlp,
4834 rdp_context->ndlp->nlp_DID, ELS_CMD_ACC);
4835 lpfc_nlp_put(ndlp);
4836 if (!elsiocb)
4837 goto free_rdp_context;
4838
4839 icmd = &elsiocb->iocb;
4840 icmd->ulpContext = rdp_context->rx_id;
4841 icmd->unsli3.rcvsli3.ox_id = rdp_context->ox_id;
4842
4843 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4844 "2171 Xmit RDP response tag x%x xri x%x, "
4845 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x",
4846 elsiocb->iotag, elsiocb->iocb.ulpContext,
4847 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
4848 ndlp->nlp_rpi);
4849 rdp_res = (struct fc_rdp_res_frame *)
4850 (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4851 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4852 memset(pcmd, 0, sizeof(struct fc_rdp_res_frame));
4853 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
4854
4855 /* For RDP payload */
4856 lpfc_rdp_res_link_service(&rdp_res->link_service_desc, ELS_CMD_RDP);
4857
4858 lpfc_rdp_res_sfp_desc(&rdp_res->sfp_desc,
4859 rdp_context->page_a0, rdp_context->page_a2);
4860 lpfc_rdp_res_speed(&rdp_res->portspeed_desc, phba);
4861 lpfc_rdp_res_link_error(&rdp_res->link_error_desc,
4862 &rdp_context->link_stat);
4863 lpfc_rdp_res_diag_port_names(&rdp_res->diag_port_names_desc, phba);
4864 lpfc_rdp_res_attach_port_names(&rdp_res->attached_port_names_desc,
4865 vport, ndlp);
4866 rdp_res->length = cpu_to_be32(RDP_DESC_PAYLOAD_SIZE);
4867
4868 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
4869
4870 phba->fc_stat.elsXmitACC++;
4871 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
4872 if (rc == IOCB_ERROR)
4873 lpfc_els_free_iocb(phba, elsiocb);
4874
4875 kfree(rdp_context);
4876
4877 return;
4878error:
4879 cmdsize = 2 * sizeof(uint32_t);
4880 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, lpfc_max_els_tries,
4881 ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
4882 lpfc_nlp_put(ndlp);
4883 if (!elsiocb)
4884 goto free_rdp_context;
4885
4886 icmd = &elsiocb->iocb;
4887 icmd->ulpContext = rdp_context->rx_id;
4888 icmd->unsli3.rcvsli3.ox_id = rdp_context->ox_id;
4889 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4890
4891 *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
4892 stat = (struct ls_rjt *)(pcmd + sizeof(uint32_t));
4893 stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4894
4895 phba->fc_stat.elsXmitLSRJT++;
4896 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
4897 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
4898
4899 if (rc == IOCB_ERROR)
4900 lpfc_els_free_iocb(phba, elsiocb);
4901free_rdp_context:
4902 kfree(rdp_context);
4903}
4904
4905int
4906lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context)
4907{
4908 LPFC_MBOXQ_t *mbox = NULL;
4909 int rc;
4910
4911 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
4912 if (!mbox) {
4913 lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_ELS,
4914 "7105 failed to allocate mailbox memory");
4915 return 1;
4916 }
4917
4918 if (lpfc_sli4_dump_page_a0(phba, mbox))
4919 goto prep_mbox_fail;
4920 mbox->vport = rdp_context->ndlp->vport;
4921 mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0;
4922 mbox->context2 = (struct lpfc_rdp_context *) rdp_context;
4923 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
4924 if (rc == MBX_NOT_FINISHED)
4925 goto issue_mbox_fail;
4926
4927 return 0;
4928
4929prep_mbox_fail:
4930issue_mbox_fail:
4931 mempool_free(mbox, phba->mbox_mem_pool);
4932 return 1;
4933}
4934
4935/*
4936 * lpfc_els_rcv_rdp - Process an unsolicited RDP ELS.
4937 * @vport: pointer to a host virtual N_Port data structure.
4938 * @cmdiocb: pointer to lpfc command iocb data structure.
4939 * @ndlp: pointer to a node-list data structure.
4940 *
4941 * This routine processes an unsolicited RDP(Read Diagnostic Parameters)
4942 * IOCB. First, the payload of the unsolicited RDP is checked.
4943 * Then it will (1) send MBX_DUMP_MEMORY, Embedded DMP_LMSD sub command TYPE-3
4944 * for Page A0, (2) send MBX_DUMP_MEMORY, DMP_LMSD for Page A2,
4945 * (3) send MBX_READ_LNK_STAT to get link stat, (4) Call lpfc_els_rdp_cmpl
4946 * gather all data and send RDP response.
4947 *
4948 * Return code
4949 * 0 - Sent the acc response
4950 * 1 - Sent the reject response.
4951 */
4952static int
4953lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4954 struct lpfc_nodelist *ndlp)
4955{
4956 struct lpfc_hba *phba = vport->phba;
4957 struct lpfc_dmabuf *pcmd;
4958 uint8_t rjt_err, rjt_expl = LSEXP_NOTHING_MORE;
4959 struct fc_rdp_req_frame *rdp_req;
4960 struct lpfc_rdp_context *rdp_context;
4961 IOCB_t *cmd = NULL;
4962 struct ls_rjt stat;
4963
4964 if (phba->sli_rev < LPFC_SLI_REV4 ||
4965 (bf_get(lpfc_sli_intf_if_type,
4966 &phba->sli4_hba.sli_intf) !=
4967 LPFC_SLI_INTF_IF_TYPE_2)) {
4968 rjt_err = LSRJT_UNABLE_TPC;
4969 rjt_expl = LSEXP_REQ_UNSUPPORTED;
4970 goto error;
4971 }
4972
4973 if (phba->sli_rev < LPFC_SLI_REV4 || (phba->hba_flag & HBA_FCOE_MODE)) {
4974 rjt_err = LSRJT_UNABLE_TPC;
4975 rjt_expl = LSEXP_REQ_UNSUPPORTED;
4976 goto error;
4977 }
4978
4979 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4980 rdp_req = (struct fc_rdp_req_frame *) pcmd->virt;
4981
4982
4983 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4984 "2422 ELS RDP Request "
4985 "dec len %d tag x%x port_id %d len %d\n",
4986 be32_to_cpu(rdp_req->rdp_des_length),
4987 be32_to_cpu(rdp_req->nport_id_desc.tag),
4988 be32_to_cpu(rdp_req->nport_id_desc.nport_id),
4989 be32_to_cpu(rdp_req->nport_id_desc.length));
4990
4991 if (sizeof(struct fc_rdp_nport_desc) !=
4992 be32_to_cpu(rdp_req->rdp_des_length))
4993 goto rjt_logerr;
4994 if (RDP_N_PORT_DESC_TAG != be32_to_cpu(rdp_req->nport_id_desc.tag))
4995 goto rjt_logerr;
4996 if (RDP_NPORT_ID_SIZE !=
4997 be32_to_cpu(rdp_req->nport_id_desc.length))
4998 goto rjt_logerr;
4999 rdp_context = kmalloc(sizeof(struct lpfc_rdp_context), GFP_KERNEL);
5000 if (!rdp_context) {
5001 rjt_err = LSRJT_UNABLE_TPC;
5002 goto error;
5003 }
5004
5005 memset(rdp_context, 0, sizeof(struct lpfc_rdp_context));
5006 cmd = &cmdiocb->iocb;
5007 rdp_context->ndlp = lpfc_nlp_get(ndlp);
5008 rdp_context->ox_id = cmd->unsli3.rcvsli3.ox_id;
5009 rdp_context->rx_id = cmd->ulpContext;
5010 rdp_context->cmpl = lpfc_els_rdp_cmpl;
5011 if (lpfc_get_rdp_info(phba, rdp_context)) {
5012 lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_ELS,
5013 "2423 Unable to send mailbox");
5014 kfree(rdp_context);
5015 rjt_err = LSRJT_UNABLE_TPC;
5016 lpfc_nlp_put(ndlp);
5017 goto error;
5018 }
5019
5020 return 0;
5021
5022rjt_logerr:
5023 rjt_err = LSRJT_LOGICAL_ERR;
5024
5025error:
5026 memset(&stat, 0, sizeof(stat));
5027 stat.un.b.lsRjtRsnCode = rjt_err;
5028 stat.un.b.lsRjtRsnCodeExp = rjt_expl;
5029 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
5030 return 1;
5031}
5032
5033
4618static void 5034static void
4619lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) 5035lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
4620{ 5036{
@@ -7052,6 +7468,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
7052 phba->fc_stat.elsRcvLCB++; 7468 phba->fc_stat.elsRcvLCB++;
7053 lpfc_els_rcv_lcb(vport, elsiocb, ndlp); 7469 lpfc_els_rcv_lcb(vport, elsiocb, ndlp);
7054 break; 7470 break;
7471 case ELS_CMD_RDP:
7472 phba->fc_stat.elsRcvRDP++;
7473 lpfc_els_rcv_rdp(vport, elsiocb, ndlp);
7474 break;
7055 case ELS_CMD_RSCN: 7475 case ELS_CMD_RSCN:
7056 phba->fc_stat.elsRcvRSCN++; 7476 phba->fc_stat.elsRcvRSCN++;
7057 lpfc_els_rcv_rscn(vport, elsiocb, ndlp); 7477 lpfc_els_rcv_rscn(vport, elsiocb, ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 6ad0a6fac9ae..892c5257d87c 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -543,6 +543,7 @@ struct fc_vft_header {
543#define ELS_CMD_TEST 0x11000000 543#define ELS_CMD_TEST 0x11000000
544#define ELS_CMD_RRQ 0x12000000 544#define ELS_CMD_RRQ 0x12000000
545#define ELS_CMD_REC 0x13000000 545#define ELS_CMD_REC 0x13000000
546#define ELS_CMD_RDP 0x18000000
546#define ELS_CMD_PRLI 0x20100014 547#define ELS_CMD_PRLI 0x20100014
547#define ELS_CMD_PRLO 0x21100014 548#define ELS_CMD_PRLO 0x21100014
548#define ELS_CMD_PRLO_ACC 0x02100014 549#define ELS_CMD_PRLO_ACC 0x02100014
@@ -581,6 +582,7 @@ struct fc_vft_header {
581#define ELS_CMD_TEST 0x11 582#define ELS_CMD_TEST 0x11
582#define ELS_CMD_RRQ 0x12 583#define ELS_CMD_RRQ 0x12
583#define ELS_CMD_REC 0x13 584#define ELS_CMD_REC 0x13
585#define ELS_CMD_RDP 0x18
584#define ELS_CMD_PRLI 0x14001020 586#define ELS_CMD_PRLI 0x14001020
585#define ELS_CMD_PRLO 0x14001021 587#define ELS_CMD_PRLO 0x14001021
586#define ELS_CMD_PRLO_ACC 0x14001002 588#define ELS_CMD_PRLO_ACC 0x14001002
@@ -1042,6 +1044,168 @@ struct fc_lcb_res_frame {
1042 uint16_t lcb_duration; /* LCB Payload Word 2, bit 15:0 */ 1044 uint16_t lcb_duration; /* LCB Payload Word 2, bit 15:0 */
1043}; 1045};
1044 1046
1047/*
1048 * Read Diagnostic Parameters (RDP) ELS frame.
1049 */
1050#define SFF_PG0_IDENT_SFP 0x3
1051
1052#define SFP_FLAG_PT_OPTICAL 0x0
1053#define SFP_FLAG_PT_SWLASER 0x01
1054#define SFP_FLAG_PT_LWLASER_LC1310 0x02
1055#define SFP_FLAG_PT_LWLASER_LL1550 0x03
1056#define SFP_FLAG_PT_MASK 0x0F
1057#define SFP_FLAG_PT_SHIFT 0
1058
1059#define SFP_FLAG_IS_OPTICAL_PORT 0x01
1060#define SFP_FLAG_IS_OPTICAL_MASK 0x010
1061#define SFP_FLAG_IS_OPTICAL_SHIFT 4
1062
1063#define SFP_FLAG_IS_DESC_VALID 0x01
1064#define SFP_FLAG_IS_DESC_VALID_MASK 0x020
1065#define SFP_FLAG_IS_DESC_VALID_SHIFT 5
1066
1067#define SFP_FLAG_CT_UNKNOWN 0x0
1068#define SFP_FLAG_CT_SFP_PLUS 0x01
1069#define SFP_FLAG_CT_MASK 0x3C
1070#define SFP_FLAG_CT_SHIFT 6
1071
1072struct fc_rdp_port_name_info {
1073 uint8_t wwnn[8];
1074 uint8_t wwpn[8];
1075};
1076
1077
1078/*
1079 * Link Error Status Block Structure (FC-FS-3) for RDP
1080 * This similar to RPS ELS
1081 */
1082struct fc_link_status {
1083 uint32_t link_failure_cnt;
1084 uint32_t loss_of_synch_cnt;
1085 uint32_t loss_of_signal_cnt;
1086 uint32_t primitive_seq_proto_err;
1087 uint32_t invalid_trans_word;
1088 uint32_t invalid_crc_cnt;
1089
1090};
1091
1092#define RDP_PORT_NAMES_DESC_TAG 0x00010003
1093struct fc_rdp_port_name_desc {
1094 uint32_t tag; /* 0001 0003h */
1095 uint32_t length; /* set to size of payload struct */
1096 struct fc_rdp_port_name_info port_names;
1097};
1098
1099
1100struct fc_rdp_link_error_status_payload_info {
1101 struct fc_link_status link_status; /* 24 bytes */
1102 uint32_t port_type; /* bits 31-30 only */
1103};
1104
1105#define RDP_LINK_ERROR_STATUS_DESC_TAG 0x00010002
1106struct fc_rdp_link_error_status_desc {
1107 uint32_t tag; /* 0001 0002h */
1108 uint32_t length; /* set to size of payload struct */
1109 struct fc_rdp_link_error_status_payload_info info;
1110};
1111
1112#define VN_PT_PHY_UNKNOWN 0x00
1113#define VN_PT_PHY_PF_PORT 0x01
1114#define VN_PT_PHY_ETH_MAC 0x10
1115#define VN_PT_PHY_SHIFT 30
1116
1117#define RDP_PS_1GB 0x8000
1118#define RDP_PS_2GB 0x4000
1119#define RDP_PS_4GB 0x2000
1120#define RDP_PS_10GB 0x1000
1121#define RDP_PS_8GB 0x0800
1122#define RDP_PS_16GB 0x0400
1123#define RDP_PS_32GB 0x0200
1124
1125#define RDP_CAP_UNKNOWN 0x0001
1126#define RDP_PS_UNKNOWN 0x0002
1127#define RDP_PS_NOT_ESTABLISHED 0x0001
1128
1129struct fc_rdp_port_speed {
1130 uint16_t capabilities;
1131 uint16_t speed;
1132};
1133
1134struct fc_rdp_port_speed_info {
1135 struct fc_rdp_port_speed port_speed;
1136};
1137
1138#define RDP_PORT_SPEED_DESC_TAG 0x00010001
1139struct fc_rdp_port_speed_desc {
1140 uint32_t tag; /* 00010001h */
1141 uint32_t length; /* set to size of payload struct */
1142 struct fc_rdp_port_speed_info info;
1143};
1144
1145#define RDP_NPORT_ID_SIZE 4
1146#define RDP_N_PORT_DESC_TAG 0x00000003
1147struct fc_rdp_nport_desc {
1148 uint32_t tag; /* 0000 0003h, big endian */
1149 uint32_t length; /* size of RDP_N_PORT_ID struct */
1150 uint32_t nport_id : 12;
1151 uint32_t reserved : 8;
1152};
1153
1154
1155struct fc_rdp_link_service_info {
1156 uint32_t els_req; /* Request payload word 0 value.*/
1157};
1158
1159#define RDP_LINK_SERVICE_DESC_TAG 0x00000001
1160struct fc_rdp_link_service_desc {
1161 uint32_t tag; /* Descriptor tag 1 */
1162 uint32_t length; /* set to size of payload struct. */
1163 struct fc_rdp_link_service_info payload;
1164 /* must be ELS req Word 0(0x18) */
1165};
1166
1167struct fc_rdp_sfp_info {
1168 uint16_t temperature;
1169 uint16_t vcc;
1170 uint16_t tx_bias;
1171 uint16_t tx_power;
1172 uint16_t rx_power;
1173 uint16_t flags;
1174};
1175
1176#define RDP_SFP_DESC_TAG 0x00010000
1177struct fc_rdp_sfp_desc {
1178 uint32_t tag;
1179 uint32_t length; /* set to size of sfp_info struct */
1180 struct fc_rdp_sfp_info sfp_info;
1181};
1182
1183struct fc_rdp_req_frame {
1184 uint32_t rdp_command; /* ELS command opcode (0x18)*/
1185 uint32_t rdp_des_length; /* RDP Payload Word 1 */
1186 struct fc_rdp_nport_desc nport_id_desc; /* RDP Payload Word 2 - 4 */
1187};
1188
1189
1190struct fc_rdp_res_frame {
1191 uint32_t reply_sequence; /* FC word0 LS_ACC or LS_RJT */
1192 uint32_t length; /* FC Word 1 */
1193 struct fc_rdp_link_service_desc link_service_desc; /* Word 2 -4 */
1194 struct fc_rdp_sfp_desc sfp_desc; /* Word 5 -9 */
1195 struct fc_rdp_port_speed_desc portspeed_desc; /* Word 10-12 */
1196 struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13-21 */
1197 struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22-27 */
1198 struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28-33 */
1199};
1200
1201
1202#define RDP_DESC_PAYLOAD_SIZE (sizeof(struct fc_rdp_link_service_desc) \
1203 + sizeof(struct fc_rdp_sfp_desc) \
1204 + sizeof(struct fc_rdp_port_speed_desc) \
1205 + sizeof(struct fc_rdp_link_error_status_desc) \
1206 + (sizeof(struct fc_rdp_port_name_desc) * 2))
1207
1208
1045/******** FDMI ********/ 1209/******** FDMI ********/
1046 1210
1047/* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */ 1211/* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */
@@ -1619,6 +1783,11 @@ typedef struct { /* FireFly BIU registers */
1619#define TEMPERATURE_OFFSET 0xB0 /* Slim offset for critical temperature event */ 1783#define TEMPERATURE_OFFSET 0xB0 /* Slim offset for critical temperature event */
1620 1784
1621/* 1785/*
1786 * return code Fail
1787 */
1788#define FAILURE 1
1789
1790/*
1622 * Begin Structure Definitions for Mailbox Commands 1791 * Begin Structure Definitions for Mailbox Commands
1623 */ 1792 */
1624 1793
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 9f2bfcc79426..7cc7bec31bfe 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -2455,6 +2455,205 @@ struct lpfc_mbx_supp_pages {
2455#define LPFC_SLI4_PARAMETERS 2 2455#define LPFC_SLI4_PARAMETERS 2
2456}; 2456};
2457 2457
2458struct lpfc_mbx_memory_dump_type3 {
2459 uint32_t word1;
2460#define lpfc_mbx_memory_dump_type3_type_SHIFT 0
2461#define lpfc_mbx_memory_dump_type3_type_MASK 0x0000000f
2462#define lpfc_mbx_memory_dump_type3_type_WORD word1
2463#define lpfc_mbx_memory_dump_type3_link_SHIFT 24
2464#define lpfc_mbx_memory_dump_type3_link_MASK 0x000000ff
2465#define lpfc_mbx_memory_dump_type3_link_WORD word1
2466 uint32_t word2;
2467#define lpfc_mbx_memory_dump_type3_page_no_SHIFT 0
2468#define lpfc_mbx_memory_dump_type3_page_no_MASK 0x0000ffff
2469#define lpfc_mbx_memory_dump_type3_page_no_WORD word2
2470#define lpfc_mbx_memory_dump_type3_offset_SHIFT 16
2471#define lpfc_mbx_memory_dump_type3_offset_MASK 0x0000ffff
2472#define lpfc_mbx_memory_dump_type3_offset_WORD word2
2473 uint32_t word3;
2474#define lpfc_mbx_memory_dump_type3_length_SHIFT 0
2475#define lpfc_mbx_memory_dump_type3_length_MASK 0x00ffffff
2476#define lpfc_mbx_memory_dump_type3_length_WORD word3
2477 uint32_t addr_lo;
2478 uint32_t addr_hi;
2479 uint32_t return_len;
2480};
2481
2482#define DMP_PAGE_A0 0xa0
2483#define DMP_PAGE_A2 0xa2
2484#define DMP_SFF_PAGE_A0_SIZE 256
2485#define DMP_SFF_PAGE_A2_SIZE 256
2486
2487#define SFP_WAVELENGTH_LC1310 1310
2488#define SFP_WAVELENGTH_LL1550 1550
2489
2490
2491/*
2492 * * SFF-8472 TABLE 3.4
2493 * */
2494#define SFF_PG0_CONNECTOR_UNKNOWN 0x00 /* Unknown */
2495#define SFF_PG0_CONNECTOR_SC 0x01 /* SC */
2496#define SFF_PG0_CONNECTOR_FC_COPPER1 0x02 /* FC style 1 copper connector */
2497#define SFF_PG0_CONNECTOR_FC_COPPER2 0x03 /* FC style 2 copper connector */
2498#define SFF_PG0_CONNECTOR_BNC 0x04 /* BNC / TNC */
2499#define SFF_PG0_CONNECTOR__FC_COAX 0x05 /* FC coaxial headers */
2500#define SFF_PG0_CONNECTOR_FIBERJACK 0x06 /* FiberJack */
2501#define SFF_PG0_CONNECTOR_LC 0x07 /* LC */
2502#define SFF_PG0_CONNECTOR_MT 0x08 /* MT - RJ */
2503#define SFF_PG0_CONNECTOR_MU 0x09 /* MU */
2504#define SFF_PG0_CONNECTOR_SF 0x0A /* SG */
2505#define SFF_PG0_CONNECTOR_OPTICAL_PIGTAIL 0x0B /* Optical pigtail */
2506#define SFF_PG0_CONNECTOR_OPTICAL_PARALLEL 0x0C /* MPO Parallel Optic */
2507#define SFF_PG0_CONNECTOR_HSSDC_II 0x20 /* HSSDC II */
2508#define SFF_PG0_CONNECTOR_COPPER_PIGTAIL 0x21 /* Copper pigtail */
2509#define SFF_PG0_CONNECTOR_RJ45 0x22 /* RJ45 */
2510
2511/* SFF-8472 Table 3.1 Diagnostics: Data Fields Address/Page A0 */
2512
2513#define SSF_IDENTIFIER 0
2514#define SSF_EXT_IDENTIFIER 1
2515#define SSF_CONNECTOR 2
2516#define SSF_TRANSCEIVER_CODE_B0 3
2517#define SSF_TRANSCEIVER_CODE_B1 4
2518#define SSF_TRANSCEIVER_CODE_B2 5
2519#define SSF_TRANSCEIVER_CODE_B3 6
2520#define SSF_TRANSCEIVER_CODE_B4 7
2521#define SSF_TRANSCEIVER_CODE_B5 8
2522#define SSF_TRANSCEIVER_CODE_B6 9
2523#define SSF_TRANSCEIVER_CODE_B7 10
2524#define SSF_ENCODING 11
2525#define SSF_BR_NOMINAL 12
2526#define SSF_RATE_IDENTIFIER 13
2527#define SSF_LENGTH_9UM_KM 14
2528#define SSF_LENGTH_9UM 15
2529#define SSF_LENGTH_50UM_OM2 16
2530#define SSF_LENGTH_62UM_OM1 17
2531#define SFF_LENGTH_COPPER 18
2532#define SSF_LENGTH_50UM_OM3 19
2533#define SSF_VENDOR_NAME 20
2534#define SSF_VENDOR_OUI 36
2535#define SSF_VENDOR_PN 40
2536#define SSF_VENDOR_REV 56
2537#define SSF_WAVELENGTH_B1 60
2538#define SSF_WAVELENGTH_B0 61
2539#define SSF_CC_BASE 63
2540#define SSF_OPTIONS_B1 64
2541#define SSF_OPTIONS_B0 65
2542#define SSF_BR_MAX 66
2543#define SSF_BR_MIN 67
2544#define SSF_VENDOR_SN 68
2545#define SSF_DATE_CODE 84
2546#define SSF_MONITORING_TYPEDIAGNOSTIC 92
2547#define SSF_ENHANCED_OPTIONS 93
2548#define SFF_8472_COMPLIANCE 94
2549#define SSF_CC_EXT 95
2550#define SSF_A0_VENDOR_SPECIFIC 96
2551
2552/* SFF-8472 Table 3.1a Diagnostics: Data Fields Address/Page A2 */
2553
2554#define SSF_AW_THRESHOLDS 0
2555#define SSF_EXT_CAL_CONSTANTS 56
2556#define SSF_CC_DMI 95
2557#define SFF_TEMPERATURE_B1 96
2558#define SFF_TEMPERATURE_B0 97
2559#define SFF_VCC_B1 98
2560#define SFF_VCC_B0 99
2561#define SFF_TX_BIAS_CURRENT_B1 100
2562#define SFF_TX_BIAS_CURRENT_B0 101
2563#define SFF_TXPOWER_B1 102
2564#define SFF_TXPOWER_B0 103
2565#define SFF_RXPOWER_B1 104
2566#define SFF_RXPOWER_B0 105
2567#define SSF_STATUS_CONTROL 110
2568#define SSF_ALARM_FLAGS_B1 112
2569#define SSF_ALARM_FLAGS_B0 113
2570#define SSF_WARNING_FLAGS_B1 116
2571#define SSF_WARNING_FLAGS_B0 117
2572#define SSF_EXT_TATUS_CONTROL_B1 118
2573#define SSF_EXT_TATUS_CONTROL_B0 119
2574#define SSF_A2_VENDOR_SPECIFIC 120
2575#define SSF_USER_EEPROM 128
2576#define SSF_VENDOR_CONTROL 148
2577
2578
2579/*
2580 * Tranceiver codes Fibre Channel SFF-8472
2581 * Table 3.5.
2582 */
2583
2584struct sff_trasnceiver_codes_byte0 {
2585 uint8_t inifiband:4;
2586 uint8_t teng_ethernet:4;
2587};
2588
2589struct sff_trasnceiver_codes_byte1 {
2590 uint8_t sonet:6;
2591 uint8_t escon:2;
2592};
2593
2594struct sff_trasnceiver_codes_byte2 {
2595 uint8_t soNet:8;
2596};
2597
2598struct sff_trasnceiver_codes_byte3 {
2599 uint8_t ethernet:8;
2600};
2601
2602struct sff_trasnceiver_codes_byte4 {
2603 uint8_t fc_el_lo:1;
2604 uint8_t fc_lw_laser:1;
2605 uint8_t fc_sw_laser:1;
2606 uint8_t fc_md_distance:1;
2607 uint8_t fc_lg_distance:1;
2608 uint8_t fc_int_distance:1;
2609 uint8_t fc_short_distance:1;
2610 uint8_t fc_vld_distance:1;
2611};
2612
2613struct sff_trasnceiver_codes_byte5 {
2614 uint8_t reserved1:1;
2615 uint8_t reserved2:1;
2616 uint8_t fc_sfp_active:1; /* Active cable */
2617 uint8_t fc_sfp_passive:1; /* Passive cable */
2618 uint8_t fc_lw_laser:1; /* Longwave laser */
2619 uint8_t fc_sw_laser_sl:1;
2620 uint8_t fc_sw_laser_sn:1;
2621 uint8_t fc_el_hi:1; /* Electrical enclosure high bit */
2622};
2623
2624struct sff_trasnceiver_codes_byte6 {
2625 uint8_t fc_tm_sm:1; /* Single Mode */
2626 uint8_t reserved:1;
2627 uint8_t fc_tm_m6:1; /* Multimode, 62.5um (M6) */
2628 uint8_t fc_tm_tv:1; /* Video Coax (TV) */
2629 uint8_t fc_tm_mi:1; /* Miniature Coax (MI) */
2630 uint8_t fc_tm_tp:1; /* Twisted Pair (TP) */
2631 uint8_t fc_tm_tw:1; /* Twin Axial Pair */
2632};
2633
2634struct sff_trasnceiver_codes_byte7 {
2635 uint8_t fc_sp_100MB:1; /* 100 MB/sec */
2636 uint8_t reserve:1;
2637 uint8_t fc_sp_200mb:1; /* 200 MB/sec */
2638 uint8_t fc_sp_3200MB:1; /* 3200 MB/sec */
2639 uint8_t fc_sp_400MB:1; /* 400 MB/sec */
2640 uint8_t fc_sp_1600MB:1; /* 1600 MB/sec */
2641 uint8_t fc_sp_800MB:1; /* 800 MB/sec */
2642 uint8_t fc_sp_1200MB:1; /* 1200 MB/sec */
2643};
2644
2645/* User writable non-volatile memory, SFF-8472 Table 3.20 */
2646struct user_eeprom {
2647 uint8_t vendor_name[16];
2648 uint8_t vendor_oui[3];
2649 uint8_t vendor_pn[816];
2650 uint8_t vendor_rev[4];
2651 uint8_t vendor_sn[16];
2652 uint8_t datecode[6];
2653 uint8_t lot_code[2];
2654 uint8_t reserved191[57];
2655};
2656
2458struct lpfc_mbx_pc_sli4_params { 2657struct lpfc_mbx_pc_sli4_params {
2459 uint32_t word1; 2658 uint32_t word1;
2460#define qs_SHIFT 0 2659#define qs_SHIFT 0
@@ -3054,6 +3253,7 @@ struct lpfc_mqe {
3054 struct lpfc_mbx_get_prof_cfg get_prof_cfg; 3253 struct lpfc_mbx_get_prof_cfg get_prof_cfg;
3055 struct lpfc_mbx_wr_object wr_object; 3254 struct lpfc_mbx_wr_object wr_object;
3056 struct lpfc_mbx_get_port_name get_port_name; 3255 struct lpfc_mbx_get_port_name get_port_name;
3256 struct lpfc_mbx_memory_dump_type3 mem_dump_type3;
3057 struct lpfc_mbx_nop nop; 3257 struct lpfc_mbx_nop nop;
3058 } un; 3258 } un;
3059}; 3259};
@@ -3199,6 +3399,7 @@ struct lpfc_acqe_fc_la {
3199#define LPFC_FC_LA_SPEED_8G 0x8 3399#define LPFC_FC_LA_SPEED_8G 0x8
3200#define LPFC_FC_LA_SPEED_10G 0xA 3400#define LPFC_FC_LA_SPEED_10G 0xA
3201#define LPFC_FC_LA_SPEED_16G 0x10 3401#define LPFC_FC_LA_SPEED_16G 0x10
3402#define LPFC_FC_LA_SPEED_32G 0x20
3202#define lpfc_acqe_fc_la_topology_SHIFT 16 3403#define lpfc_acqe_fc_la_topology_SHIFT 16
3203#define lpfc_acqe_fc_la_topology_MASK 0x000000FF 3404#define lpfc_acqe_fc_la_topology_MASK 0x000000FF
3204#define lpfc_acqe_fc_la_topology_WORD word0 3405#define lpfc_acqe_fc_la_topology_WORD word0
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 816f596cda60..eb627724417e 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -2255,6 +2255,158 @@ lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
2255 return 0; 2255 return 0;
2256} 2256}
2257 2257
2258void
2259lpfc_mbx_cmpl_rdp_link_stat(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
2260{
2261 MAILBOX_t *mb;
2262 int rc = FAILURE;
2263 struct lpfc_rdp_context *rdp_context =
2264 (struct lpfc_rdp_context *)(mboxq->context2);
2265
2266 mb = &mboxq->u.mb;
2267 if (mb->mbxStatus)
2268 goto mbx_failed;
2269
2270 memcpy(&rdp_context->link_stat, &mb->un.varRdLnk, sizeof(READ_LNK_VAR));
2271
2272 rc = SUCCESS;
2273
2274mbx_failed:
2275 lpfc_sli4_mbox_cmd_free(phba, mboxq);
2276 rdp_context->cmpl(phba, rdp_context, rc);
2277}
2278
2279void
2280lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
2281{
2282 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) mbox->context1;
2283 struct lpfc_rdp_context *rdp_context =
2284 (struct lpfc_rdp_context *)(mbox->context2);
2285
2286 if (bf_get(lpfc_mqe_status, &mbox->u.mqe))
2287 goto error;
2288
2289 lpfc_sli_bemem_bcopy(mp->virt, &rdp_context->page_a2,
2290 DMP_SFF_PAGE_A2_SIZE);
2291
2292 /* We don't need dma buffer for link stat. */
2293 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2294 kfree(mp);
2295
2296 memset(mbox, 0, sizeof(*mbox));
2297 lpfc_read_lnk_stat(phba, mbox);
2298 mbox->vport = rdp_context->ndlp->vport;
2299 mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_link_stat;
2300 mbox->context2 = (struct lpfc_rdp_context *) rdp_context;
2301 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == MBX_NOT_FINISHED)
2302 goto error;
2303
2304 return;
2305
2306error:
2307 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2308 kfree(mp);
2309 lpfc_sli4_mbox_cmd_free(phba, mbox);
2310 rdp_context->cmpl(phba, rdp_context, FAILURE);
2311}
2312
2313void
2314lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
2315{
2316 int rc;
2317 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (mbox->context1);
2318 struct lpfc_rdp_context *rdp_context =
2319 (struct lpfc_rdp_context *)(mbox->context2);
2320
2321 if (bf_get(lpfc_mqe_status, &mbox->u.mqe))
2322 goto error;
2323
2324 lpfc_sli_bemem_bcopy(mp->virt, &rdp_context->page_a0,
2325 DMP_SFF_PAGE_A0_SIZE);
2326
2327 memset(mbox, 0, sizeof(*mbox));
2328
2329 memset(mp->virt, 0, DMP_SFF_PAGE_A2_SIZE);
2330 INIT_LIST_HEAD(&mp->list);
2331
2332 /* save address for completion */
2333 mbox->context1 = mp;
2334 mbox->vport = rdp_context->ndlp->vport;
2335
2336 bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_DUMP_MEMORY);
2337 bf_set(lpfc_mbx_memory_dump_type3_type,
2338 &mbox->u.mqe.un.mem_dump_type3, DMP_LMSD);
2339 bf_set(lpfc_mbx_memory_dump_type3_link,
2340 &mbox->u.mqe.un.mem_dump_type3, phba->sli4_hba.physical_port);
2341 bf_set(lpfc_mbx_memory_dump_type3_page_no,
2342 &mbox->u.mqe.un.mem_dump_type3, DMP_PAGE_A2);
2343 bf_set(lpfc_mbx_memory_dump_type3_length,
2344 &mbox->u.mqe.un.mem_dump_type3, DMP_SFF_PAGE_A2_SIZE);
2345 mbox->u.mqe.un.mem_dump_type3.addr_lo = putPaddrLow(mp->phys);
2346 mbox->u.mqe.un.mem_dump_type3.addr_hi = putPaddrHigh(mp->phys);
2347
2348 mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a2;
2349 mbox->context2 = (struct lpfc_rdp_context *) rdp_context;
2350 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
2351 if (rc == MBX_NOT_FINISHED)
2352 goto error;
2353
2354 return;
2355
2356error:
2357 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2358 kfree(mp);
2359 lpfc_sli4_mbox_cmd_free(phba, mbox);
2360 rdp_context->cmpl(phba, rdp_context, FAILURE);
2361}
2362
2363
2364/*
2365 * lpfc_sli4_dump_sfp_pagea0 - Dump sli4 read SFP Diagnostic.
2366 * @phba: pointer to the hba structure containing.
2367 * @mbox: pointer to lpfc mbox command to initialize.
2368 *
2369 * This function create a SLI4 dump mailbox command to dump configure
2370 * type 3 page 0xA0.
2371 */
2372int
2373lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
2374{
2375 struct lpfc_dmabuf *mp = NULL;
2376
2377 memset(mbox, 0, sizeof(*mbox));
2378
2379 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
2380 if (mp)
2381 mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
2382 if (!mp || !mp->virt) {
2383 kfree(mp);
2384 lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
2385 "3569 dump type 3 page 0xA0 allocation failed\n");
2386 return 1;
2387 }
2388
2389 memset(mp->virt, 0, LPFC_BPL_SIZE);
2390 INIT_LIST_HEAD(&mp->list);
2391
2392 bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_DUMP_MEMORY);
2393 /* save address for completion */
2394 mbox->context1 = mp;
2395
2396 bf_set(lpfc_mbx_memory_dump_type3_type,
2397 &mbox->u.mqe.un.mem_dump_type3, DMP_LMSD);
2398 bf_set(lpfc_mbx_memory_dump_type3_link,
2399 &mbox->u.mqe.un.mem_dump_type3, phba->sli4_hba.physical_port);
2400 bf_set(lpfc_mbx_memory_dump_type3_page_no,
2401 &mbox->u.mqe.un.mem_dump_type3, DMP_PAGE_A0);
2402 bf_set(lpfc_mbx_memory_dump_type3_length,
2403 &mbox->u.mqe.un.mem_dump_type3, DMP_SFF_PAGE_A0_SIZE);
2404 mbox->u.mqe.un.mem_dump_type3.addr_lo = putPaddrLow(mp->phys);
2405 mbox->u.mqe.un.mem_dump_type3.addr_hi = putPaddrHigh(mp->phys);
2406
2407 return 0;
2408}
2409
2258/** 2410/**
2259 * lpfc_reg_fcfi - Initialize the REG_FCFI mailbox command 2411 * lpfc_reg_fcfi - Initialize the REG_FCFI mailbox command
2260 * @phba: pointer to the hba structure containing the FCF index and RQ ID. 2412 * @phba: pointer to the hba structure containing the FCF index and RQ ID.
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 2ce6cb58fa8d..d1a5b057c6f3 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -652,6 +652,16 @@ struct lpfc_rsrc_blks {
652 uint16_t rsrc_used; 652 uint16_t rsrc_used;
653}; 653};
654 654
655struct lpfc_rdp_context {
656 struct lpfc_nodelist *ndlp;
657 uint16_t ox_id;
658 uint16_t rx_id;
659 READ_LNK_VAR link_stat;
660 uint8_t page_a0[DMP_SFF_PAGE_A0_SIZE];
661 uint8_t page_a2[DMP_SFF_PAGE_A2_SIZE];
662 void (*cmpl)(struct lpfc_hba *, struct lpfc_rdp_context*, int);
663};
664
655struct lpfc_lcb_context { 665struct lpfc_lcb_context {
656 uint8_t sub_command; 666 uint8_t sub_command;
657 uint8_t type; 667 uint8_t type;