diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 274 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 47 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 17 |
5 files changed, 309 insertions, 34 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 7a0da125aa7d..14151de23fd7 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -121,7 +121,9 @@ struct lpfc_stats { | |||
121 | uint32_t elsRcvLOGO; | 121 | uint32_t elsRcvLOGO; |
122 | uint32_t elsRcvPRLO; | 122 | uint32_t elsRcvPRLO; |
123 | uint32_t elsRcvPRLI; | 123 | uint32_t elsRcvPRLI; |
124 | uint32_t elsRcvRRQ; | 124 | uint32_t elsRcvLIRR; |
125 | uint32_t elsRcvRPS; | ||
126 | uint32_t elsRcvRPL; | ||
125 | uint32_t elsXmitFLOGI; | 127 | uint32_t elsXmitFLOGI; |
126 | uint32_t elsXmitPLOGI; | 128 | uint32_t elsXmitPLOGI; |
127 | uint32_t elsXmitPRLI; | 129 | uint32_t elsXmitPRLI; |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index eda353b918ab..0ae49811b916 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -26,6 +26,7 @@ void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | |||
26 | void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *); | 26 | void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *); |
27 | int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *); | 27 | int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *); |
28 | void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); | 28 | void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); |
29 | void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
29 | void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); | 30 | void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); |
30 | int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *, | 31 | int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *, |
31 | uint32_t); | 32 | uint32_t); |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 20f1a0713db2..9c9e7661de59 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -2654,41 +2654,243 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, | |||
2654 | } | 2654 | } |
2655 | 2655 | ||
2656 | static int | 2656 | static int |
2657 | lpfc_els_rcv_rrq(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 2657 | lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, |
2658 | struct lpfc_nodelist * ndlp) | ||
2659 | { | ||
2660 | struct ls_rjt stat; | ||
2661 | |||
2662 | /* For now, unconditionally reject this command */ | ||
2663 | stat.un.b.lsRjtRsvd0 = 0; | ||
2664 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2665 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2666 | stat.un.b.vendorUnique = 0; | ||
2667 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2668 | return 0; | ||
2669 | } | ||
2670 | |||
2671 | void | ||
2672 | lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | ||
2673 | { | ||
2674 | struct lpfc_sli *psli; | ||
2675 | struct lpfc_sli_ring *pring; | ||
2676 | MAILBOX_t *mb; | ||
2677 | IOCB_t *icmd; | ||
2678 | RPS_RSP *rps_rsp; | ||
2679 | uint8_t *pcmd; | ||
2680 | struct lpfc_iocbq *elsiocb; | ||
2681 | struct lpfc_nodelist *ndlp; | ||
2682 | uint16_t xri, status; | ||
2683 | uint32_t cmdsize; | ||
2684 | |||
2685 | psli = &phba->sli; | ||
2686 | pring = &psli->ring[LPFC_ELS_RING]; | ||
2687 | mb = &pmb->mb; | ||
2688 | |||
2689 | ndlp = (struct lpfc_nodelist *) pmb->context2; | ||
2690 | xri = (uint16_t) ((unsigned long)(pmb->context1)); | ||
2691 | pmb->context1 = 0; | ||
2692 | pmb->context2 = 0; | ||
2693 | |||
2694 | if (mb->mbxStatus) { | ||
2695 | mempool_free( pmb, phba->mbox_mem_pool); | ||
2696 | return; | ||
2697 | } | ||
2698 | |||
2699 | cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); | ||
2700 | mempool_free( pmb, phba->mbox_mem_pool); | ||
2701 | if ((elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, 3, | ||
2702 | ndlp, ELS_CMD_ACC)) == 0) { | ||
2703 | return; | ||
2704 | } | ||
2705 | |||
2706 | icmd = &elsiocb->iocb; | ||
2707 | icmd->ulpContext = xri; | ||
2708 | |||
2709 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | ||
2710 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | ||
2711 | pcmd += sizeof (uint32_t); /* Skip past command */ | ||
2712 | rps_rsp = (RPS_RSP *)pcmd; | ||
2713 | |||
2714 | if (phba->fc_topology != TOPOLOGY_LOOP) | ||
2715 | status = 0x10; | ||
2716 | else | ||
2717 | status = 0x8; | ||
2718 | if (phba->fc_flag & FC_FABRIC) | ||
2719 | status |= 0x4; | ||
2720 | |||
2721 | rps_rsp->rsvd1 = 0; | ||
2722 | rps_rsp->portStatus = be16_to_cpu(status); | ||
2723 | rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt); | ||
2724 | rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt); | ||
2725 | rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt); | ||
2726 | rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt); | ||
2727 | rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord); | ||
2728 | rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt); | ||
2729 | |||
2730 | /* Xmit ELS RPS ACC response tag <ulpIoTag> */ | ||
2731 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | ||
2732 | "%d:0128 Xmit ELS RPS ACC response tag x%x " | ||
2733 | "Data: x%x x%x x%x x%x x%x\n", | ||
2734 | phba->brd_no, | ||
2735 | elsiocb->iocb.ulpIoTag, | ||
2736 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | ||
2737 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | ||
2738 | |||
2739 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | ||
2740 | phba->fc_stat.elsXmitACC++; | ||
2741 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | ||
2742 | lpfc_els_free_iocb(phba, elsiocb); | ||
2743 | } | ||
2744 | return; | ||
2745 | } | ||
2746 | |||
2747 | static int | ||
2748 | lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | ||
2658 | struct lpfc_nodelist * ndlp) | 2749 | struct lpfc_nodelist * ndlp) |
2659 | { | 2750 | { |
2660 | struct lpfc_dmabuf *pcmd; | ||
2661 | uint32_t *lp; | 2751 | uint32_t *lp; |
2752 | uint8_t flag; | ||
2753 | LPFC_MBOXQ_t *mbox; | ||
2754 | struct lpfc_dmabuf *pcmd; | ||
2755 | RPS *rps; | ||
2756 | struct ls_rjt stat; | ||
2757 | |||
2758 | if((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && | ||
2759 | (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { | ||
2760 | stat.un.b.lsRjtRsvd0 = 0; | ||
2761 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2762 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2763 | stat.un.b.vendorUnique = 0; | ||
2764 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2765 | } | ||
2766 | |||
2767 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
2768 | lp = (uint32_t *) pcmd->virt; | ||
2769 | flag = (be32_to_cpu(*lp++) & 0xf); | ||
2770 | rps = (RPS *) lp; | ||
2771 | |||
2772 | if ((flag == 0) || | ||
2773 | ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || | ||
2774 | ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname, | ||
2775 | sizeof (struct lpfc_name)) == 0))) { | ||
2776 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) { | ||
2777 | lpfc_read_lnk_stat(phba, mbox); | ||
2778 | mbox->context1 = | ||
2779 | (void *)((unsigned long)cmdiocb->iocb.ulpContext); | ||
2780 | mbox->context2 = ndlp; | ||
2781 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; | ||
2782 | if (lpfc_sli_issue_mbox (phba, mbox, | ||
2783 | (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { | ||
2784 | /* Mbox completion will send ELS Response */ | ||
2785 | return 0; | ||
2786 | } | ||
2787 | mempool_free(mbox, phba->mbox_mem_pool); | ||
2788 | } | ||
2789 | } | ||
2790 | stat.un.b.lsRjtRsvd0 = 0; | ||
2791 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2792 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2793 | stat.un.b.vendorUnique = 0; | ||
2794 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2795 | return 0; | ||
2796 | } | ||
2797 | |||
2798 | int | ||
2799 | lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, | ||
2800 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) | ||
2801 | { | ||
2662 | IOCB_t *icmd; | 2802 | IOCB_t *icmd; |
2803 | IOCB_t *oldcmd; | ||
2804 | RPL_RSP rpl_rsp; | ||
2805 | struct lpfc_iocbq *elsiocb; | ||
2663 | struct lpfc_sli_ring *pring; | 2806 | struct lpfc_sli_ring *pring; |
2664 | struct lpfc_sli *psli; | 2807 | struct lpfc_sli *psli; |
2665 | RRQ *rrq; | 2808 | uint8_t *pcmd; |
2666 | uint32_t cmd, did; | ||
2667 | 2809 | ||
2668 | psli = &phba->sli; | 2810 | psli = &phba->sli; |
2669 | pring = &psli->ring[LPFC_FCP_RING]; | 2811 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
2670 | icmd = &cmdiocb->iocb; | 2812 | |
2671 | did = icmd->un.elsreq64.remoteID; | 2813 | if ((elsiocb = |
2814 | lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | ||
2815 | ndlp, ELS_CMD_ACC)) == 0) { | ||
2816 | return 1; | ||
2817 | } | ||
2818 | icmd = &elsiocb->iocb; | ||
2819 | oldcmd = &oldiocb->iocb; | ||
2820 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ | ||
2821 | |||
2822 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | ||
2823 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | ||
2824 | pcmd += sizeof (uint16_t); | ||
2825 | *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize); | ||
2826 | pcmd += sizeof(uint16_t); | ||
2827 | |||
2828 | /* Setup the RPL ACC payload */ | ||
2829 | rpl_rsp.listLen = be32_to_cpu(1); | ||
2830 | rpl_rsp.index = 0; | ||
2831 | rpl_rsp.port_num_blk.portNum = 0; | ||
2832 | rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID); | ||
2833 | memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname, | ||
2834 | sizeof(struct lpfc_name)); | ||
2835 | |||
2836 | memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t)); | ||
2837 | |||
2838 | |||
2839 | /* Xmit ELS RPL ACC response tag <ulpIoTag> */ | ||
2840 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | ||
2841 | "%d:0128 Xmit ELS RPL ACC response tag x%x " | ||
2842 | "Data: x%x x%x x%x x%x x%x\n", | ||
2843 | phba->brd_no, | ||
2844 | elsiocb->iocb.ulpIoTag, | ||
2845 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | ||
2846 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | ||
2847 | |||
2848 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | ||
2849 | |||
2850 | phba->fc_stat.elsXmitACC++; | ||
2851 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | ||
2852 | lpfc_els_free_iocb(phba, elsiocb); | ||
2853 | return 1; | ||
2854 | } | ||
2855 | return 0; | ||
2856 | } | ||
2857 | |||
2858 | static int | ||
2859 | lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | ||
2860 | struct lpfc_nodelist * ndlp) | ||
2861 | { | ||
2862 | struct lpfc_dmabuf *pcmd; | ||
2863 | uint32_t *lp; | ||
2864 | uint32_t maxsize; | ||
2865 | uint16_t cmdsize; | ||
2866 | RPL *rpl; | ||
2867 | struct ls_rjt stat; | ||
2868 | |||
2869 | if((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && | ||
2870 | (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { | ||
2871 | stat.un.b.lsRjtRsvd0 = 0; | ||
2872 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
2873 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | ||
2874 | stat.un.b.vendorUnique = 0; | ||
2875 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | ||
2876 | } | ||
2877 | |||
2672 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 2878 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
2673 | lp = (uint32_t *) pcmd->virt; | 2879 | lp = (uint32_t *) pcmd->virt; |
2880 | rpl = (RPL *) (lp + 1); | ||
2674 | 2881 | ||
2675 | cmd = *lp++; | 2882 | maxsize = be32_to_cpu(rpl->maxsize); |
2676 | rrq = (RRQ *) lp; | ||
2677 | 2883 | ||
2678 | /* RRQ received */ | 2884 | /* We support only one port */ |
2679 | /* Get oxid / rxid from payload and abort it */ | 2885 | if ((rpl->index == 0) && |
2680 | spin_lock_irq(phba->host->host_lock); | 2886 | ((maxsize == 0) || |
2681 | if ((rrq->SID == be32_to_cpu(phba->fc_myDID))) { | 2887 | ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) { |
2682 | lpfc_sli_abort_iocb(phba, pring, 0, 0, rrq->Oxid, | 2888 | cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP); |
2683 | LPFC_CTX_CTX); | ||
2684 | } else { | ||
2685 | lpfc_sli_abort_iocb(phba, pring, 0, 0, rrq->Rxid, | ||
2686 | LPFC_CTX_CTX); | ||
2687 | } | 2889 | } |
2688 | 2890 | else { | |
2689 | spin_unlock_irq(phba->host->host_lock); | 2891 | cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t); |
2690 | /* ACCEPT the rrq request */ | 2892 | } |
2691 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 2893 | lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp); |
2692 | 2894 | ||
2693 | return 0; | 2895 | return 0; |
2694 | } | 2896 | } |
@@ -3201,10 +3403,6 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3201 | phba->fc_stat.elsRcvFAN++; | 3403 | phba->fc_stat.elsRcvFAN++; |
3202 | lpfc_els_rcv_fan(phba, elsiocb, ndlp); | 3404 | lpfc_els_rcv_fan(phba, elsiocb, ndlp); |
3203 | break; | 3405 | break; |
3204 | case ELS_CMD_RRQ: | ||
3205 | phba->fc_stat.elsRcvRRQ++; | ||
3206 | lpfc_els_rcv_rrq(phba, elsiocb, ndlp); | ||
3207 | break; | ||
3208 | case ELS_CMD_PRLI: | 3406 | case ELS_CMD_PRLI: |
3209 | phba->fc_stat.elsRcvPRLI++; | 3407 | phba->fc_stat.elsRcvPRLI++; |
3210 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3408 | if (phba->hba_state < LPFC_DISC_AUTH) { |
@@ -3213,9 +3411,33 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3213 | } | 3411 | } |
3214 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI); | 3412 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI); |
3215 | break; | 3413 | break; |
3414 | case ELS_CMD_LIRR: | ||
3415 | phba->fc_stat.elsRcvLIRR++; | ||
3416 | lpfc_els_rcv_lirr(phba, elsiocb, ndlp); | ||
3417 | if (newnode) { | ||
3418 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3419 | } | ||
3420 | break; | ||
3421 | case ELS_CMD_RPS: | ||
3422 | phba->fc_stat.elsRcvRPS++; | ||
3423 | lpfc_els_rcv_rps(phba, elsiocb, ndlp); | ||
3424 | if (newnode) { | ||
3425 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3426 | } | ||
3427 | break; | ||
3428 | case ELS_CMD_RPL: | ||
3429 | phba->fc_stat.elsRcvRPL++; | ||
3430 | lpfc_els_rcv_rpl(phba, elsiocb, ndlp); | ||
3431 | if (newnode) { | ||
3432 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3433 | } | ||
3434 | break; | ||
3216 | case ELS_CMD_RNID: | 3435 | case ELS_CMD_RNID: |
3217 | phba->fc_stat.elsRcvRNID++; | 3436 | phba->fc_stat.elsRcvRNID++; |
3218 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); | 3437 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); |
3438 | if (newnode) { | ||
3439 | mempool_free( ndlp, phba->nlp_mem_pool); | ||
3440 | } | ||
3219 | break; | 3441 | break; |
3220 | default: | 3442 | default: |
3221 | /* Unsupported ELS command, reject */ | 3443 | /* Unsupported ELS command, reject */ |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 1ea565e0561f..e613dd07d2ad 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -454,10 +454,13 @@ struct serv_parm { /* Structure is in Big Endian format */ | |||
454 | #define ELS_CMD_ADISC 0x52000000 | 454 | #define ELS_CMD_ADISC 0x52000000 |
455 | #define ELS_CMD_FARP 0x54000000 | 455 | #define ELS_CMD_FARP 0x54000000 |
456 | #define ELS_CMD_FARPR 0x55000000 | 456 | #define ELS_CMD_FARPR 0x55000000 |
457 | #define ELS_CMD_RPS 0x56000000 | ||
458 | #define ELS_CMD_RPL 0x57000000 | ||
457 | #define ELS_CMD_FAN 0x60000000 | 459 | #define ELS_CMD_FAN 0x60000000 |
458 | #define ELS_CMD_RSCN 0x61040000 | 460 | #define ELS_CMD_RSCN 0x61040000 |
459 | #define ELS_CMD_SCR 0x62000000 | 461 | #define ELS_CMD_SCR 0x62000000 |
460 | #define ELS_CMD_RNID 0x78000000 | 462 | #define ELS_CMD_RNID 0x78000000 |
463 | #define ELS_CMD_LIRR 0x7A000000 | ||
461 | #else /* __LITTLE_ENDIAN_BITFIELD */ | 464 | #else /* __LITTLE_ENDIAN_BITFIELD */ |
462 | #define ELS_CMD_MASK 0xffff | 465 | #define ELS_CMD_MASK 0xffff |
463 | #define ELS_RSP_MASK 0xff | 466 | #define ELS_RSP_MASK 0xff |
@@ -486,10 +489,13 @@ struct serv_parm { /* Structure is in Big Endian format */ | |||
486 | #define ELS_CMD_ADISC 0x52 | 489 | #define ELS_CMD_ADISC 0x52 |
487 | #define ELS_CMD_FARP 0x54 | 490 | #define ELS_CMD_FARP 0x54 |
488 | #define ELS_CMD_FARPR 0x55 | 491 | #define ELS_CMD_FARPR 0x55 |
492 | #define ELS_CMD_RPS 0x56 | ||
493 | #define ELS_CMD_RPL 0x57 | ||
489 | #define ELS_CMD_FAN 0x60 | 494 | #define ELS_CMD_FAN 0x60 |
490 | #define ELS_CMD_RSCN 0x0461 | 495 | #define ELS_CMD_RSCN 0x0461 |
491 | #define ELS_CMD_SCR 0x62 | 496 | #define ELS_CMD_SCR 0x62 |
492 | #define ELS_CMD_RNID 0x78 | 497 | #define ELS_CMD_RNID 0x78 |
498 | #define ELS_CMD_LIRR 0x7A | ||
493 | #endif | 499 | #endif |
494 | 500 | ||
495 | /* | 501 | /* |
@@ -758,12 +764,40 @@ typedef struct _RNID { /* Structure is in Big Endian format */ | |||
758 | } un; | 764 | } un; |
759 | } RNID; | 765 | } RNID; |
760 | 766 | ||
761 | typedef struct _RRQ { /* Structure is in Big Endian format */ | 767 | typedef struct _RPS { /* Structure is in Big Endian format */ |
762 | uint32_t SID; | 768 | union { |
763 | uint16_t Oxid; | 769 | uint32_t portNum; |
764 | uint16_t Rxid; | 770 | struct lpfc_name portName; |
765 | uint8_t resv[32]; /* optional association hdr */ | 771 | } un; |
766 | } RRQ; | 772 | } RPS; |
773 | |||
774 | typedef struct _RPS_RSP { /* Structure is in Big Endian format */ | ||
775 | uint16_t rsvd1; | ||
776 | uint16_t portStatus; | ||
777 | uint32_t linkFailureCnt; | ||
778 | uint32_t lossSyncCnt; | ||
779 | uint32_t lossSignalCnt; | ||
780 | uint32_t primSeqErrCnt; | ||
781 | uint32_t invalidXmitWord; | ||
782 | uint32_t crcCnt; | ||
783 | } RPS_RSP; | ||
784 | |||
785 | typedef struct _RPL { /* Structure is in Big Endian format */ | ||
786 | uint32_t maxsize; | ||
787 | uint32_t index; | ||
788 | } RPL; | ||
789 | |||
790 | typedef struct _PORT_NUM_BLK { | ||
791 | uint32_t portNum; | ||
792 | uint32_t portID; | ||
793 | struct lpfc_name portName; | ||
794 | } PORT_NUM_BLK; | ||
795 | |||
796 | typedef struct _RPL_RSP { /* Structure is in Big Endian format */ | ||
797 | uint32_t listLen; | ||
798 | uint32_t index; | ||
799 | PORT_NUM_BLK port_num_blk; | ||
800 | } RPL_RSP; | ||
767 | 801 | ||
768 | /* This is used for RSCN command */ | 802 | /* This is used for RSCN command */ |
769 | typedef struct _D_ID { /* Structure is in Big Endian format */ | 803 | typedef struct _D_ID { /* Structure is in Big Endian format */ |
@@ -804,7 +838,6 @@ typedef struct _ELS_PKT { /* Structure is in Big Endian format */ | |||
804 | FARP farp; /* Payload for FARP/ACC */ | 838 | FARP farp; /* Payload for FARP/ACC */ |
805 | FAN fan; /* Payload for FAN */ | 839 | FAN fan; /* Payload for FAN */ |
806 | SCR scr; /* Payload for SCR/ACC */ | 840 | SCR scr; /* Payload for SCR/ACC */ |
807 | RRQ rrq; /* Payload for RRQ */ | ||
808 | RNID rnid; /* Payload for RNID */ | 841 | RNID rnid; /* Payload for RNID */ |
809 | uint8_t pad[128 - 4]; /* Pad out to payload of 128 bytes */ | 842 | uint8_t pad[128 - 4]; /* Pad out to payload of 128 bytes */ |
810 | } un; | 843 | } un; |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index e3bc8d3f7302..6c4b21a32c7f 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -336,6 +336,23 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
336 | return; | 336 | return; |
337 | } | 337 | } |
338 | 338 | ||
339 | /*************************************************/ | ||
340 | /* lpfc_read_lnk_stat Issue a READ LINK STATUS */ | ||
341 | /* mailbox command */ | ||
342 | /*************************************************/ | ||
343 | void | ||
344 | lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | ||
345 | { | ||
346 | MAILBOX_t *mb; | ||
347 | |||
348 | mb = &pmb->mb; | ||
349 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | ||
350 | |||
351 | mb->mbxCommand = MBX_READ_LNK_STAT; | ||
352 | mb->mbxOwner = OWN_HOST; | ||
353 | return; | ||
354 | } | ||
355 | |||
339 | /********************************************/ | 356 | /********************************************/ |
340 | /* lpfc_reg_login Issue a REG_LOGIN */ | 357 | /* lpfc_reg_login Issue a REG_LOGIN */ |
341 | /* mailbox command */ | 358 | /* mailbox command */ |