diff options
author | James Smart <james.smart@avagotech.com> | 2015-05-21 13:55:21 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-06-06 01:34:55 -0400 |
commit | 86478875eb4d2e7108b914f8a5e53be260816d5c (patch) | |
tree | 9f97de6ec770e84e276bfd83d147243ec1428477 /drivers/scsi | |
parent | a1efe163102fed8a3b5990a67cadb1193e630820 (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.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 420 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 169 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 201 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 152 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 10 |
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 *, | |||
498 | bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *, | 498 | bool 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 *); |
501 | int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox); | ||
502 | void 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 | ||
4618 | void | ||
4619 | lpfc_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 | |||
4628 | void | ||
4629 | lpfc_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 | |||
4691 | void | ||
4692 | lpfc_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 | |||
4718 | void | ||
4719 | lpfc_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 | |||
4775 | void | ||
4776 | lpfc_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 | |||
4791 | void | ||
4792 | lpfc_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 | |||
4814 | void | ||
4815 | lpfc_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; | ||
4878 | error: | ||
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); | ||
4901 | free_rdp_context: | ||
4902 | kfree(rdp_context); | ||
4903 | } | ||
4904 | |||
4905 | int | ||
4906 | lpfc_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 | |||
4929 | prep_mbox_fail: | ||
4930 | issue_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 | */ | ||
4952 | static int | ||
4953 | lpfc_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 | |||
5022 | rjt_logerr: | ||
5023 | rjt_err = LSRJT_LOGICAL_ERR; | ||
5024 | |||
5025 | error: | ||
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 | |||
4618 | static void | 5034 | static void |
4619 | lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 5035 | lpfc_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 | |||
1072 | struct 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 | */ | ||
1082 | struct 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 | ||
1093 | struct 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 | |||
1100 | struct 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 | ||
1106 | struct 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 | |||
1129 | struct fc_rdp_port_speed { | ||
1130 | uint16_t capabilities; | ||
1131 | uint16_t speed; | ||
1132 | }; | ||
1133 | |||
1134 | struct fc_rdp_port_speed_info { | ||
1135 | struct fc_rdp_port_speed port_speed; | ||
1136 | }; | ||
1137 | |||
1138 | #define RDP_PORT_SPEED_DESC_TAG 0x00010001 | ||
1139 | struct 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 | ||
1147 | struct 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 | |||
1155 | struct 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 | ||
1160 | struct 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 | |||
1167 | struct 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 | ||
1177 | struct 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 | |||
1183 | struct 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 | |||
1190 | struct 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 | ||
2458 | struct 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 | |||
2584 | struct sff_trasnceiver_codes_byte0 { | ||
2585 | uint8_t inifiband:4; | ||
2586 | uint8_t teng_ethernet:4; | ||
2587 | }; | ||
2588 | |||
2589 | struct sff_trasnceiver_codes_byte1 { | ||
2590 | uint8_t sonet:6; | ||
2591 | uint8_t escon:2; | ||
2592 | }; | ||
2593 | |||
2594 | struct sff_trasnceiver_codes_byte2 { | ||
2595 | uint8_t soNet:8; | ||
2596 | }; | ||
2597 | |||
2598 | struct sff_trasnceiver_codes_byte3 { | ||
2599 | uint8_t ethernet:8; | ||
2600 | }; | ||
2601 | |||
2602 | struct 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 | |||
2613 | struct 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 | |||
2624 | struct 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 | |||
2634 | struct 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 */ | ||
2646 | struct 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 | |||
2458 | struct lpfc_mbx_pc_sli4_params { | 2657 | struct 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 | ||
2258 | void | ||
2259 | lpfc_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 | |||
2274 | mbx_failed: | ||
2275 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
2276 | rdp_context->cmpl(phba, rdp_context, rc); | ||
2277 | } | ||
2278 | |||
2279 | void | ||
2280 | lpfc_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 | |||
2306 | error: | ||
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 | |||
2313 | void | ||
2314 | lpfc_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 | |||
2356 | error: | ||
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 | */ | ||
2372 | int | ||
2373 | lpfc_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 | ||
655 | struct 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 | |||
655 | struct lpfc_lcb_context { | 665 | struct lpfc_lcb_context { |
656 | uint8_t sub_command; | 666 | uint8_t sub_command; |
657 | uint8_t type; | 667 | uint8_t type; |