[SCSI] bfa: direct attach mode fix.
authorKrishna Gudipati <kgudipat@brocade.com>
Tue, 14 Dec 2010 00:17:42 +0000 (16:17 -0800)
committerJames Bottomley <James.Bottomley@suse.de>
Tue, 21 Dec 2010 18:37:16 +0000 (12:37 -0600)
- Direct attach is not working due to the check of PID in fcxp_send request.
- Added logic to set the lps->lp_pid with the PID assigned for n2n mode.

Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfa_svc.c
drivers/scsi/bfa/bfa_svc.h
drivers/scsi/bfa/bfi_ms.h

index f0e652b50994a6d14d36bd9eb560bd0176b6cf86..0fd63168573f2bb42d2318917fcaf00026a049dd 100644 (file)
@@ -38,6 +38,7 @@ enum bfa_lps_event {
        BFA_LPS_SM_DELETE       = 5,    /* lps delete from user         */
        BFA_LPS_SM_OFFLINE      = 6,    /* Link is offline              */
        BFA_LPS_SM_RX_CVL       = 7,    /* Rx clear virtual link        */
+       BFA_LPS_SM_SET_N2N_PID  = 8,    /* Set assigned PID for n2n */
 };
 
 
index aa4516672eed9379daa876c40cbcfa179fe80a26..4f2e4e095d67ac9a9b64ab73b05845b3c87c59de 100644 (file)
@@ -309,6 +309,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
                        return;
                }
                port->pid  = rx_fchs->d_id;
+               bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
        }
 
        /*
@@ -323,6 +324,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
                        (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
                        (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
                        port->pid  = rx_fchs->d_id;
+                       bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
                        rport->pid = rx_fchs->s_id;
                }
                bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
@@ -979,6 +981,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
            ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
             sizeof(wwn_t)) > 0) {
                port->pid = N2N_LOCAL_PID;
+               bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
                /*
                 * First, check if we know the device by pwwn.
                 */
index 2666472d142906c74bd24c848316be0cb60ca6d5..b7df5534da857834edf300d282399603fcf24f89 100644 (file)
@@ -131,6 +131,7 @@ static void bfa_lps_reqq_resume(void *lps_arg);
 static void bfa_lps_free(struct bfa_lps_s *lps);
 static void bfa_lps_send_login(struct bfa_lps_s *lps);
 static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
 static void bfa_lps_login_comp(struct bfa_lps_s *lps);
 static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
 static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
@@ -143,6 +144,8 @@ static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
 static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
                                        event);
 static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
+                                       enum bfa_lps_event event);
 static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
 static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
                                        event);
@@ -1254,6 +1257,12 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
                        else
                                bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
                                        BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
+                       /* If N2N, send the assigned PID to FW */
+                       bfa_trc(lps->bfa, lps->fport);
+                       bfa_trc(lps->bfa, lps->lp_pid);
+
+                       if (!lps->fport && lps->lp_pid)
+                               bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
                } else {
                        bfa_sm_set_state(lps, bfa_lps_sm_init);
                        if (lps->fdisc)
@@ -1272,6 +1281,11 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
                bfa_sm_set_state(lps, bfa_lps_sm_init);
                break;
 
+       case BFA_LPS_SM_SET_N2N_PID:
+               bfa_trc(lps->bfa, lps->fport);
+               bfa_trc(lps->bfa, lps->lp_pid);
+               break;
+
        default:
                bfa_sm_fault(lps->bfa, event);
        }
@@ -1340,6 +1354,14 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
                        BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
                break;
 
+       case BFA_LPS_SM_SET_N2N_PID:
+               if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+                       bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
+                       bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+               } else
+                       bfa_lps_send_set_n2n_pid(lps);
+               break;
+
        case BFA_LPS_SM_OFFLINE:
        case BFA_LPS_SM_DELETE:
                bfa_sm_set_state(lps, bfa_lps_sm_init);
@@ -1350,6 +1372,48 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
        }
 }
 
+/**
+ * login complete
+ */
+static void
+bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, event);
+
+       switch (event) {
+       case BFA_LPS_SM_RESUME:
+               bfa_sm_set_state(lps, bfa_lps_sm_online);
+               bfa_lps_send_set_n2n_pid(lps);
+               break;
+
+       case BFA_LPS_SM_LOGOUT:
+               bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+               bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+                       BFA_PL_EID_LOGO, 0, "Logout");
+               break;
+
+       case BFA_LPS_SM_RX_CVL:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               bfa_reqq_wcancel(&lps->wqe);
+
+               /* Let the vport module know about this event */
+               bfa_lps_cvl_event(lps);
+               bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+                       BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
+               break;
+
+       case BFA_LPS_SM_OFFLINE:
+       case BFA_LPS_SM_DELETE:
+               bfa_sm_set_state(lps, bfa_lps_sm_init);
+               bfa_reqq_wcancel(&lps->wqe);
+               break;
+
+       default:
+               bfa_sm_fault(lps->bfa, event);
+       }
+}
+
 /*
  * logout in progress - awaiting firmware response
  */
@@ -1498,8 +1562,9 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
        switch (rsp->status) {
        case BFA_STATUS_OK:
                lps->fport      = rsp->f_port;
+               if (lps->fport)
+                       lps->lp_pid = rsp->lp_pid;
                lps->npiv_en    = rsp->npiv_en;
-               lps->lp_pid     = rsp->lp_pid;
                lps->pr_bbcred  = be16_to_cpu(rsp->bb_credit);
                lps->pr_pwwn    = rsp->port_name;
                lps->pr_nwwn    = rsp->node_name;
@@ -1626,6 +1691,25 @@ bfa_lps_send_logout(struct bfa_lps_s *lps)
        bfa_reqq_produce(lps->bfa, lps->reqq);
 }
 
+/**
+ * send n2n pid set request to firmware
+ */
+static void
+bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
+{
+       struct bfi_lps_n2n_pid_req_s *m;
+
+       m = bfa_reqq_next(lps->bfa, lps->reqq);
+       bfa_assert(m);
+
+       bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
+               bfa_lpuid(lps->bfa));
+
+       m->lp_tag = lps->lp_tag;
+       m->lp_pid = lps->lp_pid;
+       bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
 /*
  * Indirect login completion handler for non-fcs
  */
@@ -1846,6 +1930,19 @@ bfa_lps_get_base_pid(struct bfa_s *bfa)
        return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
 }
 
+/**
+ * Set PID in case of n2n (which is assigned during PLOGI)
+ */
+void
+bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
+{
+       bfa_trc(lps->bfa, lps->lp_tag);
+       bfa_trc(lps->bfa, n2n_pid);
+
+       lps->lp_pid = n2n_pid;
+       bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
+}
+
 /*
  * LPS firmware message class handler.
  */
index 36c81c74f04aacb482f97ed2ae59532046f2b0d5..331ad992a5812c53f02a4f0cf2d1e0911b2965da 100644 (file)
@@ -610,6 +610,7 @@ void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
 void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
                   wwn_t pwwn, wwn_t nwwn);
 void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
+void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid);
 u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
 u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
 void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
index 8f22ef1a6ed9940aa6f70c0e3752ac6d4c2f6cd3..19e888a57555accff45b49a870973146b9df7892 100644 (file)
@@ -342,6 +342,7 @@ struct bfi_uf_frm_rcvd_s {
 enum bfi_lps_h2i_msgs {
        BFI_LPS_H2I_LOGIN_REQ   = 1,
        BFI_LPS_H2I_LOGOUT_REQ  = 2,
+       BFI_LPS_H2I_N2N_PID_REQ = 3,
 };
 
 enum bfi_lps_i2h_msgs {
@@ -401,10 +402,17 @@ struct bfi_lps_cvl_event_s {
        u8              rsvd[3];
 };
 
+struct bfi_lps_n2n_pid_req_s {
+       struct bfi_mhdr_s       mh;     /*  common msg header           */
+       u8      lp_tag;
+       u32     lp_pid:24;
+};
+
 union bfi_lps_h2i_msg_u {
        struct bfi_mhdr_s               *msg;
        struct bfi_lps_login_req_s      *login_req;
        struct bfi_lps_logout_req_s     *logout_req;
+       struct bfi_lps_n2n_pid_req_s    *n2n_pid_req;
 };
 
 union bfi_lps_i2h_msg_u {