diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index ed1e728763a2..93d1fbe4ee5d 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -2767,6 +2767,40 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, | |||
2767 | ibmvfc_init_tgt(tgt, job_step); | 2767 | ibmvfc_init_tgt(tgt, job_step); |
2768 | } | 2768 | } |
2769 | 2769 | ||
2770 | /* Defined in FC-LS */ | ||
2771 | static const struct { | ||
2772 | int code; | ||
2773 | int retry; | ||
2774 | int logged_in; | ||
2775 | } prli_rsp [] = { | ||
2776 | { 0, 1, 0 }, | ||
2777 | { 1, 0, 1 }, | ||
2778 | { 2, 1, 0 }, | ||
2779 | { 3, 1, 0 }, | ||
2780 | { 4, 0, 0 }, | ||
2781 | { 5, 0, 0 }, | ||
2782 | { 6, 0, 1 }, | ||
2783 | { 7, 0, 0 }, | ||
2784 | { 8, 1, 0 }, | ||
2785 | }; | ||
2786 | |||
2787 | /** | ||
2788 | * ibmvfc_get_prli_rsp - Find PRLI response index | ||
2789 | * @flags: PRLI response flags | ||
2790 | * | ||
2791 | **/ | ||
2792 | static int ibmvfc_get_prli_rsp(u16 flags) | ||
2793 | { | ||
2794 | int i; | ||
2795 | int code = (flags & 0x0f00) >> 8; | ||
2796 | |||
2797 | for (i = 0; i < ARRAY_SIZE(prli_rsp); i++) | ||
2798 | if (prli_rsp[i].code == code) | ||
2799 | return i; | ||
2800 | |||
2801 | return 0; | ||
2802 | } | ||
2803 | |||
2770 | /** | 2804 | /** |
2771 | * ibmvfc_tgt_prli_done - Completion handler for Process Login | 2805 | * ibmvfc_tgt_prli_done - Completion handler for Process Login |
2772 | * @evt: ibmvfc event struct | 2806 | * @evt: ibmvfc event struct |
@@ -2777,15 +2811,36 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) | |||
2777 | struct ibmvfc_target *tgt = evt->tgt; | 2811 | struct ibmvfc_target *tgt = evt->tgt; |
2778 | struct ibmvfc_host *vhost = evt->vhost; | 2812 | struct ibmvfc_host *vhost = evt->vhost; |
2779 | struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; | 2813 | struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; |
2814 | struct ibmvfc_prli_svc_parms *parms = &rsp->parms; | ||
2780 | u32 status = rsp->common.status; | 2815 | u32 status = rsp->common.status; |
2816 | int index; | ||
2781 | 2817 | ||
2782 | vhost->discovery_threads--; | 2818 | vhost->discovery_threads--; |
2783 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); | 2819 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); |
2784 | switch (status) { | 2820 | switch (status) { |
2785 | case IBMVFC_MAD_SUCCESS: | 2821 | case IBMVFC_MAD_SUCCESS: |
2786 | tgt_dbg(tgt, "Process Login succeeded\n"); | 2822 | tgt_dbg(tgt, "Process Login succeeded: %X %02X %04X\n", |
2787 | tgt->need_login = 0; | 2823 | parms->type, parms->flags, parms->service_parms); |
2788 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT); | 2824 | |
2825 | if (parms->type == IBMVFC_SCSI_FCP_TYPE) { | ||
2826 | index = ibmvfc_get_prli_rsp(parms->flags); | ||
2827 | if (prli_rsp[index].logged_in) { | ||
2828 | if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) { | ||
2829 | tgt->need_login = 0; | ||
2830 | tgt->ids.roles = 0; | ||
2831 | if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC) | ||
2832 | tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; | ||
2833 | if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC) | ||
2834 | tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; | ||
2835 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT); | ||
2836 | } else | ||
2837 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); | ||
2838 | } else if (prli_rsp[index].retry) | ||
2839 | ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); | ||
2840 | else | ||
2841 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); | ||
2842 | } else | ||
2843 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); | ||
2789 | break; | 2844 | break; |
2790 | case IBMVFC_MAD_DRIVER_FAILED: | 2845 | case IBMVFC_MAD_DRIVER_FAILED: |
2791 | break; | 2846 | break; |
@@ -2874,7 +2929,6 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) | |||
2874 | tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); | 2929 | tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); |
2875 | tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); | 2930 | tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); |
2876 | tgt->ids.port_id = tgt->scsi_id; | 2931 | tgt->ids.port_id = tgt->scsi_id; |
2877 | tgt->ids.roles = FC_PORT_ROLE_FCP_TARGET; | ||
2878 | memcpy(&tgt->service_parms, &rsp->service_parms, | 2932 | memcpy(&tgt->service_parms, &rsp->service_parms, |
2879 | sizeof(tgt->service_parms)); | 2933 | sizeof(tgt->service_parms)); |
2880 | memcpy(&tgt->service_parms_change, &rsp->service_parms_change, | 2934 | memcpy(&tgt->service_parms_change, &rsp->service_parms_change, |