summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c62
1 files changed, 58 insertions, 4 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index ed1e728763a..93d1fbe4ee5 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,
ibmvfc_init_tgt(tgt, job_step);
}
+/* Defined in FC-LS */
+static const struct {
+ int code;
+ int retry;
+ int logged_in;
+} prli_rsp [] = {
+ { 0, 1, 0 },
+ { 1, 0, 1 },
+ { 2, 1, 0 },
+ { 3, 1, 0 },
+ { 4, 0, 0 },
+ { 5, 0, 0 },
+ { 6, 0, 1 },
+ { 7, 0, 0 },
+ { 8, 1, 0 },
+};
+
+/**
+ * ibmvfc_get_prli_rsp - Find PRLI response index
+ * @flags: PRLI response flags
+ *
+ **/
+static int ibmvfc_get_prli_rsp(u16 flags)
+{
+ int i;
+ int code = (flags & 0x0f00) >> 8;
+
+ for (i = 0; i < ARRAY_SIZE(prli_rsp); i++)
+ if (prli_rsp[i].code == code)
+ return i;
+
+ return 0;
+}
+
/**
* ibmvfc_tgt_prli_done - Completion handler for Process Login
* @evt: ibmvfc event struct
@@ -2777,15 +2811,36 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli;
+ struct ibmvfc_prli_svc_parms *parms = &rsp->parms;
u32 status = rsp->common.status;
+ int index;
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
switch (status) {
case IBMVFC_MAD_SUCCESS:
- tgt_dbg(tgt, "Process Login succeeded\n");
- tgt->need_login = 0;
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT);
+ tgt_dbg(tgt, "Process Login succeeded: %X %02X %04X\n",
+ parms->type, parms->flags, parms->service_parms);
+
+ if (parms->type == IBMVFC_SCSI_FCP_TYPE) {
+ index = ibmvfc_get_prli_rsp(parms->flags);
+ if (prli_rsp[index].logged_in) {
+ if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) {
+ tgt->need_login = 0;
+ tgt->ids.roles = 0;
+ if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC)
+ tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
+ if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
+ tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT);
+ } else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ } else if (prli_rsp[index].retry)
+ ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
+ else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ } else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
@@ -2874,7 +2929,6 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name);
tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name);
tgt->ids.port_id = tgt->scsi_id;
- tgt->ids.roles = FC_PORT_ROLE_FCP_TARGET;
memcpy(&tgt->service_parms, &rsp->service_parms,
sizeof(tgt->service_parms));
memcpy(&tgt->service_parms_change, &rsp->service_parms_change,