[SCSI] bfa: Add support for FC Arbitrated Loop topology.
authorKrishna Gudipati <kgudipat@brocade.com>
Sat, 22 Sep 2012 00:23:59 +0000 (17:23 -0700)
committerJames Bottomley <JBottomley@Parallels.com>
Sun, 7 Oct 2012 10:03:50 +0000 (11:03 +0100)
- Add private loop topology support at 2G/4G/8G speeds with following
  limitations
  1. No support for multiple initiators in the loop
  2. No public loop support. If attached to a loop with an FL_Port,
     device continues to work as a private NL_Port in the loop
  3. No auto topology detection. User has to manually set the
     configured topology to loop if attaching to loop.
- When loop topology is configured, enabling FC port features
  QoS/Trunk/TRL are not allowed and vice versa.

Signed-off-by: Vijaya Mohan Guvva <vmohan@brocade.com>
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
12 files changed:
drivers/scsi/bfa/bfa_defs.h
drivers/scsi/bfa/bfa_defs_svc.h
drivers/scsi/bfa/bfa_fc.h
drivers/scsi/bfa/bfa_fcbuild.c
drivers/scsi/bfa/bfa_fcs.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfa_fcs_rport.c
drivers/scsi/bfa/bfa_svc.c
drivers/scsi/bfa/bfa_svc.h
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bfa/bfi_ms.h

index b5a1595cc0a523f6e71e8b1c8c438257c5897f70..f1c9314e86a360fb4617203c120ba153c90b1023 100644 (file)
@@ -159,6 +159,8 @@ enum bfa_status {
        BFA_STATUS_BEACON_ON    = 72,   /* Port Beacon already on */
        BFA_STATUS_ENOFSAVE     = 78,   /*  No saved firmware trace */
        BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
+       BFA_STATUS_ERROR_TRL_ENABLED  = 87,   /* TRL is enabled */
+       BFA_STATUS_ERROR_QOS_ENABLED  = 88,   /* QoS is enabled */
        BFA_STATUS_NO_SFP_DEV = 89,     /* No SFP device check or replace SFP */
        BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact support */
        BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */
@@ -184,6 +186,9 @@ enum bfa_status {
        BFA_STATUS_FAA_ACQ_ADDR = 200,  /* Acquiring addr */
        BFA_STATUS_ERROR_TRUNK_ENABLED = 203,   /* Trunk enabled on adapter */
        BFA_STATUS_MAX_ENTRY_REACHED = 212,     /* MAX entry reached */
+       BFA_STATUS_TOPOLOGY_LOOP = 230, /* Topology is set to Loop */
+       BFA_STATUS_LOOP_UNSUPP_MEZZ = 231, /* Loop topology is not supported
+                                           * on mezz cards */
        BFA_STATUS_MAX_VAL              /* Unknown error code */
 };
 #define bfa_status_t enum bfa_status
index 36756ce0e58f63dcb34736ef5834c7641bdcb323..20749f1933818553f284a90329fe6ed8abbd8f8c 100644 (file)
@@ -324,12 +324,46 @@ struct bfa_fw_fcoe_port_stats_s {
        struct bfa_fw_fip_stats_s               fip_stats;
 };
 
+/**
+ * @brief LPSM statistics
+ */
+struct bfa_fw_lpsm_stats_s {
+       u32     cls_rx;         /* LPSM cls_rx                  */
+       u32     cls_tx;         /* LPSM cls_tx                  */
+       u32     arbf0_rx;       /* LPSM abrf0 rcvd              */
+       u32     arbf0_tx;       /* LPSM abrf0 xmit              */
+       u32     init_rx;        /* LPSM loop init start         */
+       u32     unexp_hwst;     /* LPSM unknown hw state        */
+       u32     unexp_frame;    /* LPSM unknown_frame           */
+       u32     unexp_prim;     /* LPSM unexpected primitive    */
+       u32     prev_alpa_unavail; /* LPSM prev alpa unavailable */
+       u32     alpa_unavail;   /* LPSM alpa not available      */
+       u32     lip_rx;         /* LPSM lip rcvd                */
+       u32     lip_f7f7_rx;    /* LPSM lip f7f7 rcvd           */
+       u32     lip_f8_rx;      /* LPSM lip f8 rcvd             */
+       u32     lip_f8f7_rx;    /* LPSM lip f8f7 rcvd           */
+       u32     lip_other_rx;   /* LPSM lip other rcvd          */
+       u32     lip_tx;         /* LPSM lip xmit                */
+       u32     retry_tov;      /* LPSM retry TOV               */
+       u32     lip_tov;        /* LPSM LIP wait TOV            */
+       u32     idle_tov;       /* LPSM idle wait TOV           */
+       u32     arbf0_tov;      /* LPSM arbfo wait TOV          */
+       u32     stop_loop_tov;  /* LPSM stop loop wait TOV      */
+       u32     lixa_tov;       /* LPSM lisa wait TOV           */
+       u32     lixx_tov;       /* LPSM lilp/lirp wait TOV      */
+       u32     cls_tov;        /* LPSM cls wait TOV            */
+       u32     sler;           /* LPSM SLER recvd              */
+       u32     failed;         /* LPSM failed                  */
+       u32     success;        /* LPSM online                  */
+};
+
 /*
  * IOC firmware FC uport stats
  */
 struct bfa_fw_fc_uport_stats_s {
        struct bfa_fw_port_snsm_stats_s         snsm_stats;
        struct bfa_fw_port_lksm_stats_s         lksm_stats;
+       struct bfa_fw_lpsm_stats_s              lpsm_stats;
 };
 
 /*
@@ -357,11 +391,6 @@ struct bfa_fw_fcxchg_stats_s {
        u32     ua_state_inv;
 };
 
-struct bfa_fw_lpsm_stats_s {
-       u32     cls_rx;
-       u32     cls_tx;
-};
-
 /*
  *  Trunk statistics
  */
@@ -454,7 +483,6 @@ struct bfa_fw_stats_s {
        struct bfa_fw_io_stats_s        io_stats;
        struct bfa_fw_port_stats_s      port_stats;
        struct bfa_fw_fcxchg_stats_s    fcxchg_stats;
-       struct bfa_fw_lpsm_stats_s      lpsm_stats;
        struct bfa_fw_lps_stats_s       lps_stats;
        struct bfa_fw_trunk_stats_s     trunk_stats;
        struct bfa_fw_advsm_stats_s     advsm_stats;
@@ -498,9 +526,10 @@ enum bfa_qos_bw_alloc {
  * QoS attribute returned in QoS Query
  */
 struct bfa_qos_attr_s {
-       u8              state;          /*  QoS current state */
-       u8              rsvd[3];
-       u32  total_bb_cr;               /*  Total BB Credits */
+       u8      state;          /*  QoS current state */
+       u8      rsvd1[3];
+       u32     total_bb_cr;    /*  Total BB Credits */
+       u32     rsvd2[2];
 };
 
 /*
@@ -714,9 +743,11 @@ enum bfa_port_type {
  */
 enum bfa_port_topology {
        BFA_PORT_TOPOLOGY_NONE = 0,     /*  No valid topology */
-       BFA_PORT_TOPOLOGY_P2P  = 1,     /*  P2P only */
-       BFA_PORT_TOPOLOGY_LOOP = 2,     /*  LOOP topology */
-       BFA_PORT_TOPOLOGY_AUTO = 3,     /*  auto topology selection */
+       BFA_PORT_TOPOLOGY_P2P_OLD_VER = 1, /* P2P def for older ver */
+       BFA_PORT_TOPOLOGY_LOOP = 2,     /* LOOP topology */
+       BFA_PORT_TOPOLOGY_AUTO_OLD_VER = 3, /* auto def for older ver */
+       BFA_PORT_TOPOLOGY_AUTO = 4,     /* auto topology selection */
+       BFA_PORT_TOPOLOGY_P2P = 5,      /* P2P only */
 };
 
 /*
@@ -851,9 +882,10 @@ struct bfa_port_cfg_s {
        u8       bb_scn;        /*  BB_SCN value from FLOGI Exchg */
        u8       bb_scn_state;  /*  Config state of BB_SCN */
        u8       faa_state;     /*  FAA enabled/disabled        */
-       u8       rsvd[1];
+       u8       rsvd1;
        u16      path_tov;      /*  device path timeout */
        u16      q_depth;       /*  SCSI Queue depth            */
+       u32      rsvd2;
 };
 #pragma pack()
 
@@ -971,6 +1003,13 @@ struct bfa_trunk_vc_attr_s {
        u16 vc_credits[8];
 };
 
+struct bfa_fcport_loop_info_s {
+       u8      myalpa;         /* alpa claimed */
+       u8      alpabm_val;     /* alpa bitmap valid or not (1 or 0) */
+       u8      resvd[6];
+       struct fc_alpabm_s alpabm;      /* alpa bitmap */
+};
+
 /*
  *     Link state information
  */
@@ -981,13 +1020,18 @@ struct bfa_port_link_s {
        u8       speed;         /*  Link speed (1/2/4/8 G) */
        u32      linkstate_opt; /*  Linkstate optional data (debug) */
        u8       trunked;       /*  Trunked or not (1 or 0) */
-       u8       resvd[3];
+       u8       resvd[7];
        struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
        union {
-               struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
-               struct bfa_trunk_vc_attr_s trunk_vc_attr;
-               struct bfa_fcport_fcf_s fcf; /*  FCF information (for FCoE) */
-       } vc_fcf;
+               struct bfa_fcport_loop_info_s loop_info;
+               union {
+                       struct bfa_qos_vc_attr_s qos_vc_attr;
+                                       /*  VC info from ELP */
+                       struct bfa_trunk_vc_attr_s trunk_vc_attr;
+                       struct bfa_fcport_fcf_s fcf;
+                                       /*  FCF information (for FCoE) */
+               } vc_fcf;
+       } attr;
 };
 #pragma pack()
 
@@ -1112,6 +1156,9 @@ struct bfa_port_fc_stats_s {
        u64     tx_frames;      /*  Tx frames                   */
        u64     tx_words;       /*  Tx words                    */
        u64     tx_lip;         /*  Tx LIP                      */
+       u64     tx_lip_f7f7;    /*  Tx LIP_F7F7         */
+       u64     tx_lip_f8f7;    /*  Tx LIP_F8F7         */
+       u64     tx_arbf0;       /*  Tx ARB F0                   */
        u64     tx_nos;         /*  Tx NOS                      */
        u64     tx_ols;         /*  Tx OLS                      */
        u64     tx_lr;          /*  Tx LR                       */
@@ -1119,6 +1166,9 @@ struct bfa_port_fc_stats_s {
        u64     rx_frames;      /*  Rx frames                   */
        u64     rx_words;       /*  Rx words                    */
        u64     lip_count;      /*  Rx LIP                      */
+       u64     rx_lip_f7f7;    /*  Rx LIP_F7F7         */
+       u64     rx_lip_f8f7;    /*  Rx LIP_F8F7         */
+       u64     rx_arbf0;       /*  Rx ARB F0                   */
        u64     nos_count;      /*  Rx NOS                      */
        u64     ols_count;      /*  Rx OLS                      */
        u64     lr_count;       /*  Rx LR                       */
@@ -1140,6 +1190,7 @@ struct bfa_port_fc_stats_s {
        u64     bbsc_frames_lost; /* Credit Recovery-Frames Lost  */
        u64     bbsc_credits_lost; /* Credit Recovery-Credits Lost */
        u64     bbsc_link_resets; /* Credit Recovery-Link Resets   */
+       u64     loop_timeouts;  /*  Loop timeouts               */
 };
 
 /*
index e0beb4d7e26443c8881abc3ba66f59b7ac773f87..bea821b9803041086339c3e0b5973ab1df0893d5 100644 (file)
@@ -24,6 +24,7 @@ typedef u64 wwn_t;
 
 #define WWN_NULL       (0)
 #define FC_SYMNAME_MAX 256     /*  max name server symbolic name size */
+#define FC_ALPA_MAX    128
 
 #pragma pack(1)
 
@@ -1015,6 +1016,10 @@ struct fc_symname_s {
        u8         symname[FC_SYMNAME_MAX];
 };
 
+struct fc_alpabm_s {
+       u8      alpa_bm[FC_ALPA_MAX / 8];
+};
+
 /*
  * protocol default timeout values
  */
index 273cee90b3b429166ef8259a81a60aad0a865dc4..dce787f6cca2e421169e8f80b4f9a228b0f1bf4f 100644 (file)
@@ -228,6 +228,10 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 
        memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 
+       /* For FC AL bb_cr is 0 and altbbcred is 1 */
+       if (!bb_cr)
+               plogi->csp.altbbcred = 1;
+
        plogi->els_cmd.els_code = els_code;
        if (els_code == FC_ELS_PLOGI)
                fc_els_req_build(fchs, d_id, s_id, ox_id);
index fd3e84d32bd2fed636b61a443f32ebe71f3c54a1..d428808fb37ef7cb0ec1f3cfb41d4bedf974e014 100644 (file)
@@ -303,16 +303,30 @@ static void
 bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
                          enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_START:
-               if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+               if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+                       break;
+               }
+               if (bfa_fcport_get_topology(bfa) ==
+                               BFA_PORT_TOPOLOGY_LOOP) {
+                       fabric->fab_type = BFA_FCS_FABRIC_LOOP;
+                       fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
+                       fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
+                       bfa_sm_set_state(fabric,
+                                       bfa_fcs_fabric_sm_online);
+                       bfa_fcs_fabric_set_opertype(fabric);
+                       bfa_fcs_lport_online(&fabric->bport);
+               } else {
                        bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
                        bfa_fcs_fabric_login(fabric);
-               } else
-                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+               }
                break;
 
        case BFA_FCS_FABRIC_SM_LINK_UP:
@@ -337,16 +351,28 @@ static void
 bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
                           enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_LINK_UP:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-               bfa_fcs_fabric_login(fabric);
+               if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+                       bfa_fcs_fabric_login(fabric);
+                       break;
+               }
+               fabric->fab_type = BFA_FCS_FABRIC_LOOP;
+               fabric->bport.pid = bfa_fcport_get_myalpa(bfa);
+               fabric->bport.pid = bfa_hton3b(fabric->bport.pid);
+               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+               bfa_fcs_fabric_set_opertype(fabric);
+               bfa_fcs_lport_online(&fabric->bport);
                break;
 
        case BFA_FCS_FABRIC_SM_RETRY_OP:
+       case BFA_FCS_FABRIC_SM_LOOPBACK:
                break;
 
        case BFA_FCS_FABRIC_SM_DELETE:
@@ -595,14 +621,20 @@ void
 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
                         enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_LINK_DOWN:
                bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-               bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
-               bfa_fcs_fabric_notify_offline(fabric);
+               if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
+                       bfa_fcs_lport_offline(&fabric->bport);
+               } else {
+                       bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
+                       bfa_fcs_fabric_notify_offline(fabric);
+               }
                break;
 
        case BFA_FCS_FABRIC_SM_DELETE:
@@ -719,20 +751,29 @@ static void
 bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,
                           enum bfa_fcs_fabric_event event)
 {
+       struct bfa_s    *bfa = fabric->fcs->bfa;
+
        bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
        bfa_trc(fabric->fcs, event);
 
        switch (event) {
        case BFA_FCS_FABRIC_SM_STOPCOMP:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
-               bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
+               if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+               } else {
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+                       bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);
+               }
                break;
 
        case BFA_FCS_FABRIC_SM_LINK_UP:
                break;
 
        case BFA_FCS_FABRIC_SM_LINK_DOWN:
-               bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
+               if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+               else
+                       bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);
                break;
 
        default:
@@ -975,9 +1016,6 @@ bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
        struct bfa_lport_cfg_s  *pcfg = &fabric->bport.port_cfg;
        u8                      alpa = 0, bb_scn = 0;
 
-       if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
-               alpa = bfa_fcport_get_myalpa(bfa);
-
        if (bfa_fcs_fabric_is_bbscn_enabled(fabric) &&
            (!fabric->fcs->bbscn_flogi_rjt))
                bb_scn = BFA_FCS_PORT_DEF_BB_SCN;
index 6c4377cb287f1eec93791c8d56bd401c28a5f731..f2a6a3c0e00255fde89d561c595f9bbfe118d2c3 100644 (file)
@@ -118,9 +118,9 @@ struct bfa_fcs_lport_fab_s {
 #define        MAX_ALPA_COUNT  127
 
 struct bfa_fcs_lport_loop_s {
-       u8         num_alpa;    /*  Num of ALPA entries in the map */
-       u8         alpa_pos_map[MAX_ALPA_COUNT];        /*  ALPA Positional
-                                                        *Map */
+       u8      num_alpa;       /*  Num of ALPA entries in the map */
+       u8      alpabm_valid;   /* alpa bitmap valid or not (1 or 0) */
+       u8      alpa_pos_map[MAX_ALPA_COUNT]; /*  ALPA Positional Map */
        struct bfa_fcs_lport_s *port;   /*  parent port */
 };
 
@@ -175,6 +175,7 @@ enum bfa_fcs_fabric_type {
        BFA_FCS_FABRIC_UNKNOWN = 0,
        BFA_FCS_FABRIC_SWITCHED = 1,
        BFA_FCS_FABRIC_N2N = 2,
+       BFA_FCS_FABRIC_LOOP = 3,
 };
 
 
@@ -350,9 +351,10 @@ void               bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg,
                                struct bfa_fcxp_s *fcxp_alloced);
 void            bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
 void            bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
-void            bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *vport);
 void            bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
                                              struct fchs_s *rx_frame, u32 len);
+void           bfa_fcs_lport_lip_scn_online(bfa_fcs_lport_t *port);
 
 struct bfa_fcs_vport_s {
        struct list_head                qe;             /*  queue elem  */
@@ -453,6 +455,7 @@ struct bfa_fcs_rport_s {
        struct bfa_rport_stats_s stats; /*  rport stats */
        enum bfa_rport_function scsi_function;  /*  Initiator/Target */
        struct bfa_fcs_rpf_s rpf;       /* Rport features module */
+       bfa_boolean_t   scn_online;     /* SCN online flag */
 };
 
 static inline struct bfa_rport_s *
@@ -733,7 +736,7 @@ enum rport_event {
        RPSM_EVENT_LOGO_IMP     = 5,    /*  implicit logo for SLER      */
        RPSM_EVENT_FCXP_SENT    = 6,    /*  Frame from has been sent    */
        RPSM_EVENT_DELETE       = 7,    /*  RPORT delete request        */
-       RPSM_EVENT_SCN          = 8,    /*  state change notification   */
+       RPSM_EVENT_FAB_SCN      = 8,    /*  state change notification   */
        RPSM_EVENT_ACCEPTED     = 9,    /*  Good response from remote device */
        RPSM_EVENT_FAILED       = 10,   /*  Request to rport failed.    */
        RPSM_EVENT_TIMEOUT      = 11,   /*  Rport SM timeout event      */
@@ -744,7 +747,9 @@ enum rport_event {
        RPSM_EVENT_ADDRESS_DISC = 16,   /*  Need to Discover rport's PID */
        RPSM_EVENT_PRLO_RCVD   = 17,    /*  PRLO from remote device     */
        RPSM_EVENT_PLOGI_RETRY = 18,    /*  Retry PLOGI continuously */
-       RPSM_EVENT_FC4_FCS_ONLINE = 19, /*!< FC-4 FCS online complete */
+       RPSM_EVENT_SCN_OFFLINE = 19,    /* loop scn offline             */
+       RPSM_EVENT_SCN_ONLINE   = 20,   /* loop scn online              */
+       RPSM_EVENT_FC4_FCS_ONLINE = 21, /* FC-4 FCS online complete */
 };
 
 /*
@@ -763,7 +768,7 @@ enum bfa_fcs_itnim_event {
        BFA_FCS_ITNIM_SM_DELETE = 10,   /*  delete event from rport */
        BFA_FCS_ITNIM_SM_PRLO = 11,     /*  delete event from rport */
        BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
-       BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /*!< bfa rport online event */
+       BFA_FCS_ITNIM_SM_HAL_ONLINE = 13, /* bfa rport online event */
 };
 
 /*
index 3b75f6fb2de1fbf29b189715e5a3af9d17283343..c58a5e03d56fc785e37c3b492e1a282e9247688a 100644 (file)
 
 BFA_TRC_FILE(FCS, PORT);
 
+/*
+ * ALPA to LIXA bitmap mapping
+ *
+ * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
+ * is for L_bit (login required) and is filled as ALPA 0x00 here.
+ */
+static const u8 loop_alpa_map[] = {
+       0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, /* Word 0 Bits 31..24 */
+       0x17, 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, /* Word 0 Bits 23..16 */
+       0x26, 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, /* Word 0 Bits 15..08 */
+       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, /* Word 0 Bits 07..00 */
+
+       0x3C, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, /* Word 1 Bits 31..24 */
+       0x4C, 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, /* Word 1 Bits 23..16 */
+       0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, /* Word 1 Bits 15..08 */
+       0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, /* Word 1 Bits 07..00 */
+
+       0x73, 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, /* Word 2 Bits 31..24 */
+       0x81, 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, /* Word 2 Bits 23..16 */
+       0x9B, 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, /* Word 2 Bits 15..08 */
+       0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, /* Word 2 Bits 07..00 */
+
+       0xB3, 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, /* Word 3 Bits 31..24 */
+       0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, /* Word 3 Bits 23..16 */
+       0xCE, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, /* Word 3 Bits 15..08 */
+       0xDA, 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF, /* Word 3 Bits 07..00 */
+};
+
 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
                                         struct fchs_s *rx_fchs, u8 reason_code,
                                         u8 reason_code_expl);
@@ -51,6 +79,10 @@ static void  bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
 static void    bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
 static void    bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
 
+static void    bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port);
+static void    bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port);
+static void    bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port);
+
 static struct {
        void            (*init) (struct bfa_fcs_lport_s *port);
        void            (*online) (struct bfa_fcs_lport_s *port);
@@ -62,7 +94,9 @@ static struct {
        bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
                        bfa_fcs_lport_fab_offline}, {
        bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
-                       bfa_fcs_lport_n2n_offline},
+                       bfa_fcs_lport_n2n_offline}, {
+       bfa_fcs_lport_loop_init, bfa_fcs_lport_loop_online,
+                       bfa_fcs_lport_loop_offline},
        };
 
 /*
@@ -1127,7 +1161,7 @@ static void
 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
 {
        bfa_fcs_lport_ns_online(port);
-       bfa_fcs_lport_scn_online(port);
+       bfa_fcs_lport_fab_scn_online(port);
 }
 
 /*
@@ -1221,6 +1255,98 @@ bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
        n2n_port->reply_oxid = 0;
 }
 
+void
+bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port)
+{
+       int i = 0, j = 0, bit = 0, alpa_bit = 0;
+       u8 k = 0;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(port->fcs->bfa);
+
+       port->port_topo.ploop.alpabm_valid = fcport->alpabm_valid;
+       port->pid = fcport->myalpa;
+       port->pid = bfa_hton3b(port->pid);
+
+       for (i = 0; i < (FC_ALPA_MAX / 8); i++) {
+               for (j = 0, alpa_bit = 0; j < 8; j++, alpa_bit++) {
+                       bfa_trc(port->fcs->bfa, fcport->alpabm.alpa_bm[i]);
+                       bit = (fcport->alpabm.alpa_bm[i] & (1 << (7 - j)));
+                       if (bit) {
+                               port->port_topo.ploop.alpa_pos_map[k] =
+                                       loop_alpa_map[(i * 8) + alpa_bit];
+                               k++;
+                               bfa_trc(port->fcs->bfa, k);
+                               bfa_trc(port->fcs->bfa,
+                                        port->port_topo.ploop.alpa_pos_map[k]);
+                       }
+               }
+       }
+       port->port_topo.ploop.num_alpa = k;
+}
+
+/*
+ * Called by fcs/port to initialize Loop topology.
+ */
+static void
+bfa_fcs_lport_loop_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/*
+ * Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_loop_online(struct bfa_fcs_lport_s *port)
+{
+       u8 num_alpa = 0, alpabm_valid = 0;
+       struct bfa_fcs_rport_s *rport;
+       u8 *alpa_map = NULL;
+       int i = 0;
+       u32 pid;
+
+       bfa_fcport_get_loop_attr(port);
+
+       num_alpa = port->port_topo.ploop.num_alpa;
+       alpabm_valid = port->port_topo.ploop.alpabm_valid;
+       alpa_map = port->port_topo.ploop.alpa_pos_map;
+
+       bfa_trc(port->fcs->bfa, port->pid);
+       bfa_trc(port->fcs->bfa, num_alpa);
+       if (alpabm_valid == 1) {
+               for (i = 0; i < num_alpa; i++) {
+                       bfa_trc(port->fcs->bfa, alpa_map[i]);
+                       if (alpa_map[i] != bfa_hton3b(port->pid)) {
+                               pid = alpa_map[i];
+                               bfa_trc(port->fcs->bfa, pid);
+                               rport = bfa_fcs_lport_get_rport_by_pid(port,
+                                               bfa_hton3b(pid));
+                               if (!rport)
+                                       rport = bfa_fcs_rport_create(port,
+                                               bfa_hton3b(pid));
+                       }
+               }
+       } else {
+               for (i = 0; i < MAX_ALPA_COUNT; i++) {
+                       if (alpa_map[i] != port->pid) {
+                               pid = loop_alpa_map[i];
+                               bfa_trc(port->fcs->bfa, pid);
+                               rport = bfa_fcs_lport_get_rport_by_pid(port,
+                                               bfa_hton3b(pid));
+                               if (!rport)
+                                       rport = bfa_fcs_rport_create(port,
+                                               bfa_hton3b(pid));
+                       }
+               }
+       }
+}
+
+/*
+ * Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_loop_offline(struct bfa_fcs_lport_s *port)
+{
+}
+
 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
 
 /*
@@ -5199,7 +5325,7 @@ bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
 }
 
 void
-bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+bfa_fcs_lport_fab_scn_online(struct bfa_fcs_lport_s *port)
 {
        struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
 
@@ -5620,6 +5746,15 @@ bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
        memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
 }
 
+/*
+ * Let new loop map create missing rports
+ */
+void
+bfa_fcs_lport_lip_scn_online(struct bfa_fcs_lport_s *port)
+{
+       bfa_fcs_lport_loop_online(port);
+}
+
 /*
  * FCS virtual port state machine
  */
index cc43b2a58ce33ac9478cc25b9c9fc0509f4eeb96..e90800d0557aa5e666da1a2f90648ec7e8ae80da 100644 (file)
@@ -106,9 +106,13 @@ static void        bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
                                                 enum rport_event event);
 static void    bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
                                         enum rport_event event);
-static void    bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-                                               enum rport_event event);
-static void    bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+static void    bfa_fcs_rport_sm_adisc_online_sending(
+                       struct bfa_fcs_rport_s *rport, enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+                                       enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
+                                       *rport, enum rport_event event);
+static void    bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
                                        enum rport_event event);
 static void    bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
                                                enum rport_event event);
@@ -150,8 +154,10 @@ static struct bfa_sm_table_s rport_sm_table[] = {
        {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
        {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
        {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
-       {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
-       {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
+       {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
        {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
        {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
        {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
@@ -231,10 +237,19 @@ bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /* query the NS */
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -280,12 +295,20 @@ bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
 
        case RPSM_EVENT_PLOGI_RCVD:
        case RPSM_EVENT_PLOGI_COMP:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * Ignore, SCN is possibly online notification.
                 */
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
@@ -346,9 +369,19 @@ bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_stop(&rport->timer);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                bfa_timer_stop(&rport->timer);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -422,7 +455,18 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
                }
                break;
 
-       case    RPSM_EVENT_PLOGI_RETRY:
+       case RPSM_EVENT_SCN_ONLINE:
+               break;
+
+       case RPSM_EVENT_SCN_OFFLINE:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                               bfa_fcs_rport_timeout, rport,
+                               bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RETRY:
                rport->plogi_retries = 0;
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
                bfa_timer_start(rport->fcs->bfa, &rport->timer,
@@ -440,8 +484,10 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
                break;
 
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                bfa_fcxp_discard(rport->fcxp);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
@@ -512,7 +558,8 @@ bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_PLOGI_COMP:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
@@ -561,9 +608,10 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_fcs_offline_action(rport);
                break;
@@ -595,14 +643,15 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
        bfa_trc(rport->fcs, event);
 
        switch (event) {
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
                        bfa_sm_set_state(rport,
                                         bfa_fcs_rport_sm_nsquery_sending);
                        rport->ns_retries = 0;
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
                } else {
-                       bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+                       bfa_sm_set_state(rport,
+                               bfa_fcs_rport_sm_adisc_online_sending);
                        bfa_fcs_rport_send_adisc(rport, NULL);
                }
                break;
@@ -610,6 +659,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
        case RPSM_EVENT_PLOGI_RCVD:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
+       case RPSM_EVENT_SCN_OFFLINE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
                bfa_fcs_rport_hal_offline_action(rport);
                break;
@@ -625,6 +675,7 @@ bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
        case RPSM_EVENT_PLOGI_COMP:
                break;
 
@@ -656,7 +707,7 @@ bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * ignore SCN, wait for response to query itself
                 */
@@ -696,7 +747,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
 
        switch (event) {
        case RPSM_EVENT_ACCEPTED:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
                bfa_fcs_rport_send_adisc(rport, NULL);
                break;
 
@@ -718,7 +769,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                break;
 
        case RPSM_EVENT_LOGO_RCVD:
@@ -747,7 +798,7 @@ bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
  *     authenticating with rport. FC-4s are paused.
  */
 static void
-bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
         enum rport_event event)
 {
        bfa_trc(rport->fcs, rport->pwwn);
@@ -756,7 +807,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
 
        switch (event) {
        case RPSM_EVENT_FCXP_SENT:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
                break;
 
        case RPSM_EVENT_DELETE:
@@ -779,7 +830,7 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                break;
 
        case RPSM_EVENT_PLOGI_RCVD:
@@ -798,7 +849,8 @@ bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
  *             FC-4s are paused.
  */
 static void
-bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
+                               enum rport_event event)
 {
        bfa_trc(rport->fcs, rport->pwwn);
        bfa_trc(rport->fcs, rport->pid);
@@ -831,7 +883,7 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_hal_offline_action(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * already processing RSCN
                 */
@@ -856,7 +908,96 @@ bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
 }
 
 /*
- *             Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ * ADISC is being sent for authenticating with rport
+ * Already did offline actions.
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
+       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_FCXP_SENT:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa,
+                       &rport->fcxp_wqe);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * ADISC to rport
+ * Already did offline actions
+ */
+static void
+bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
+                       enum rport_event event)
+{
+       bfa_trc(rport->fcs, rport->pwwn);
+       bfa_trc(rport->fcs, rport->pid);
+       bfa_trc(rport->fcs, event);
+
+       switch (event) {
+       case RPSM_EVENT_ACCEPTED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+               bfa_fcs_rport_hal_online(rport);
+               break;
+
+       case RPSM_EVENT_PLOGI_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_fcs_rport_send_plogiacc(rport, NULL);
+               break;
+
+       case RPSM_EVENT_FAILED:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       case RPSM_EVENT_DELETE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_LOGO_RCVD:
+       case RPSM_EVENT_PRLO_RCVD:
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+               bfa_fcxp_discard(rport->fcxp);
+               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                       bfa_fcs_rport_timeout, rport,
+                       bfa_fcs_rport_del_timeout);
+               break;
+
+       default:
+               bfa_sm_fault(rport->fcs, event);
+       }
+}
+
+/*
+ * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
  */
 static void
 bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
@@ -881,6 +1022,8 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_HCB_ONLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
@@ -945,6 +1088,8 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_hal_offline(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+               break;
        case RPSM_EVENT_LOGO_RCVD:
                /*
                 * Rport is going offline. Just ack the logo
@@ -956,8 +1101,9 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_prlo_acc(rport);
                break;
 
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_HCB_ONLINE:
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_IMP:
        case RPSM_EVENT_ADDRESS_CHANGE:
                /*
@@ -1015,6 +1161,19 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
                                bfa_fcs_rport_sm_nsdisc_sending);
                        rport->ns_retries = 0;
                        bfa_fcs_rport_send_nsdisc(rport, NULL);
+               } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==
+                                       BFA_PORT_TOPOLOGY_LOOP) {
+                       if (rport->scn_online) {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_adisc_offline_sending);
+                               bfa_fcs_rport_send_adisc(rport, NULL);
+                       } else {
+                               bfa_sm_set_state(rport,
+                                       bfa_fcs_rport_sm_offline);
+                               bfa_timer_start(rport->fcs->bfa, &rport->timer,
+                                       bfa_fcs_rport_timeout, rport,
+                                       bfa_fcs_rport_del_timeout);
+                       }
                } else {
                        bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
                        rport->plogi_retries = 0;
@@ -1027,7 +1186,9 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_RCVD:
@@ -1106,6 +1267,8 @@ bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
                /*
@@ -1146,6 +1309,8 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
@@ -1172,7 +1337,9 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_SCN_ONLINE:
+       case RPSM_EVENT_SCN_OFFLINE:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
                break;
 
@@ -1209,10 +1376,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_free(rport);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
-               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                bfa_timer_stop(&rport->timer);
+               WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
+                                       BFA_PORT_TOPOLOGY_LOOP));
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                rport->ns_retries = 0;
                bfa_fcs_rport_send_nsdisc(rport, NULL);
                break;
@@ -1232,6 +1401,7 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_LOGO_IMP:
+       case RPSM_EVENT_SCN_OFFLINE:
                break;
 
        case RPSM_EVENT_PLOGI_COMP:
@@ -1240,6 +1410,12 @@ bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
                bfa_fcs_rport_fcs_online_action(rport);
                break;
 
+       case RPSM_EVENT_SCN_ONLINE:
+               bfa_timer_stop(&rport->timer);
+               bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+               bfa_fcs_rport_send_plogi(rport, NULL);
+               break;
+
        case RPSM_EVENT_PLOGI_SEND:
                bfa_timer_stop(&rport->timer);
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
@@ -1280,7 +1456,7 @@ bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_plogiacc(rport, NULL);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_LOGO_RCVD:
        case RPSM_EVENT_PRLO_RCVD:
        case RPSM_EVENT_PLOGI_SEND:
@@ -1326,7 +1502,7 @@ bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
                bfa_fcs_rport_send_nsdisc(rport, NULL);
                break;
 
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
        case RPSM_EVENT_ADDRESS_CHANGE:
                bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
                bfa_timer_stop(&rport->timer);
@@ -1439,7 +1615,7 @@ bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
        case RPSM_EVENT_PRLO_RCVD:
                bfa_fcs_rport_send_prlo_acc(rport);
                break;
-       case RPSM_EVENT_SCN:
+       case RPSM_EVENT_FAB_SCN:
                /*
                 * ignore, wait for NS query response
                 */
@@ -2546,7 +2722,7 @@ void
 bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
 {
        rport->stats.rscns++;
-       bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+       bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
 }
 
 /*
@@ -2621,6 +2797,48 @@ bfa_cb_rport_qos_scn_flowid(void *cbarg,
        bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
 }
 
+void
+bfa_cb_rport_scn_online(struct bfa_s *bfa)
+{
+       struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+       struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+       struct bfa_fcs_rport_s *rp;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rp = (struct bfa_fcs_rport_s *) qe;
+               bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
+               rp->scn_online = BFA_TRUE;
+       }
+
+       if (bfa_fcs_lport_is_online(port))
+               bfa_fcs_lport_lip_scn_online(port);
+}
+
+void
+bfa_cb_rport_scn_no_dev(void *rport)
+{
+       struct bfa_fcs_rport_s *rp = rport;
+
+       bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+       rp->scn_online = BFA_FALSE;
+}
+
+void
+bfa_cb_rport_scn_offline(struct bfa_s *bfa)
+{
+       struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
+       struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
+       struct bfa_fcs_rport_s *rp;
+       struct list_head *qe;
+
+       list_for_each(qe, &port->rport_q) {
+               rp = (struct bfa_fcs_rport_s *) qe;
+               bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
+               rp->scn_online = BFA_FALSE;
+       }
+}
+
 /*
  *     brief
  *     This routine is a static BFA callback when there is a QoS priority
index b2538d60db34aab67dc8ec69c8da7f49bb05b122..fcad11629f103fa3c0442f70838853257cb77af0 100644 (file)
@@ -1244,6 +1244,12 @@ bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
                 * Just ignore
                 */
                break;
+       case BFA_LPS_SM_SET_N2N_PID:
+               /*
+                * When topology is set to loop, bfa_lps_set_n2n_pid() sends
+                * this event. Ignore this event.
+                */
+               break;
 
        default:
                bfa_sm_fault(lps->bfa, event);
@@ -1261,6 +1267,7 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
 
        switch (event) {
        case BFA_LPS_SM_FWRSP:
+       case BFA_LPS_SM_OFFLINE:
                if (lps->status == BFA_STATUS_OK) {
                        bfa_sm_set_state(lps, bfa_lps_sm_online);
                        if (lps->fdisc)
@@ -1289,7 +1296,6 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
                bfa_lps_login_comp(lps);
                break;
 
-       case BFA_LPS_SM_OFFLINE:
        case BFA_LPS_SM_DELETE:
                bfa_sm_set_state(lps, bfa_lps_sm_init);
                break;
@@ -2250,11 +2256,11 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
                if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
 
                        bfa_trc(fcport->bfa,
-                               pevent->link_state.vc_fcf.fcf.fipenabled);
+                               pevent->link_state.attr.vc_fcf.fcf.fipenabled);
                        bfa_trc(fcport->bfa,
-                               pevent->link_state.vc_fcf.fcf.fipfailed);
+                               pevent->link_state.attr.vc_fcf.fcf.fipfailed);
 
-                       if (pevent->link_state.vc_fcf.fcf.fipfailed)
+                       if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
                                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                        BFA_PL_EID_FIP_FCF_DISC, 0,
                                        "FIP FCF Discovery Failed");
@@ -2996,6 +3002,21 @@ bfa_fcport_iocdisable(struct bfa_s *bfa)
        bfa_trunk_iocdisable(bfa);
 }
 
+/*
+ * Update loop info in fcport for SCN online
+ */
+static void
+bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
+                       struct bfa_fcport_loop_info_s *loop_info)
+{
+       fcport->myalpa = loop_info->myalpa;
+       fcport->alpabm_valid =
+                       loop_info->alpabm_val;
+       memcpy(fcport->alpabm.alpa_bm,
+                       loop_info->alpabm.alpa_bm,
+                       sizeof(struct fc_alpabm_s));
+}
+
 static void
 bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
 {
@@ -3005,12 +3026,15 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
        fcport->speed = pevent->link_state.speed;
        fcport->topology = pevent->link_state.topology;
 
-       if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
-               fcport->myalpa = 0;
+       if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
+               bfa_fcport_update_loop_info(fcport,
+                               &pevent->link_state.attr.loop_info);
+               return;
+       }
 
        /* QoS Details */
        fcport->qos_attr = pevent->link_state.qos_attr;
-       fcport->qos_vc_attr = pevent->link_state.vc_fcf.qos_vc_attr;
+       fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
 
        /*
         * update trunk state if applicable
@@ -3019,7 +3043,8 @@ bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
                trunk->attr.state = BFA_TRUNK_DISABLED;
 
        /* update FCoE specific */
-       fcport->fcoe_vlan = be16_to_cpu(pevent->link_state.vc_fcf.fcf.vlan);
+       fcport->fcoe_vlan =
+               be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
 
        bfa_trc(fcport->bfa, fcport->speed);
        bfa_trc(fcport->bfa, fcport->topology);
@@ -3609,6 +3634,9 @@ bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
 
        if (fcport->cfg.trunked == BFA_TRUE)
                return BFA_STATUS_TRUNK_ENABLED;
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+                       (speed == BFA_PORT_SPEED_16GBPS))
+               return BFA_STATUS_UNSUPP_SPEED;
        if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
                bfa_trc(bfa, fcport->speed_sup);
                return BFA_STATUS_UNSUPP_SPEED;
@@ -3663,7 +3691,24 @@ bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
 
        switch (topology) {
        case BFA_PORT_TOPOLOGY_P2P:
+               break;
+
        case BFA_PORT_TOPOLOGY_LOOP:
+               if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
+                       (fcport->qos_attr.state != BFA_QOS_DISABLED))
+                       return BFA_STATUS_ERROR_QOS_ENABLED;
+               if (fcport->cfg.ratelimit != BFA_FALSE)
+                       return BFA_STATUS_ERROR_TRL_ENABLED;
+               if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
+                       (fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
+                       return BFA_STATUS_ERROR_TRUNK_ENABLED;
+               if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
+                       (fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
+                       return BFA_STATUS_UNSUPP_SPEED;
+               if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
+                       return BFA_STATUS_LOOP_UNSUPP_MEZZ;
+               break;
+
        case BFA_PORT_TOPOLOGY_AUTO:
                break;
 
@@ -3686,6 +3731,17 @@ bfa_fcport_get_topology(struct bfa_s *bfa)
        return fcport->topology;
 }
 
+/**
+ * Get config topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
+{
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+       return fcport->cfg.topology;
+}
+
 bfa_status_t
 bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
 {
@@ -3761,9 +3817,11 @@ bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
 u8
 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
 {
-       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+       if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
+               return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
 
-       return fcport->cfg.rx_bbcredit;
+       else
+               return 0;
 }
 
 void
@@ -4707,6 +4765,21 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
                bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
                break;
 
+       case BFI_RPORT_I2H_LIP_SCN_ONLINE:
+               bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
+                               &msg.lip_scn->loop_info);
+               bfa_cb_rport_scn_online(bfa);
+               break;
+
+       case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
+               bfa_cb_rport_scn_offline(bfa);
+               break;
+
+       case BFI_RPORT_I2H_NO_DEV:
+               rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
+               bfa_cb_rport_scn_no_dev(rp->rport_drv);
+               break;
+
        default:
                bfa_trc(bfa, m->mhdr.msg_id);
                WARN_ON(1);
index 1abcf7c51661f68cdbe286f29dda5363b2ccb5d9..2d1cd4349bcde92b9af406111523dc746dcc50e3 100644 (file)
@@ -474,8 +474,10 @@ struct bfa_fcport_s {
        /*  supported speeds */
        enum bfa_port_speed speed;      /*  current speed */
        enum bfa_port_topology topology;        /*  current topology */
-       u8                      myalpa; /*  my ALPA in LOOP topology */
        u8                      rsvd[3];
+       u8                      myalpa; /*  my ALPA in LOOP topology */
+       u8                      alpabm_valid; /* alpa bitmap valid or not */
+       struct fc_alpabm_s      alpabm; /* alpa bitmap */
        struct bfa_port_cfg_s   cfg;    /*  current port configuration */
        bfa_boolean_t           use_flash_cfg; /* get port cfg from flash */
        struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
@@ -534,6 +536,7 @@ enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
                                     enum bfa_port_topology topo);
 enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa);
+enum bfa_port_topology bfa_fcport_get_cfg_topology(struct bfa_s *bfa);
 bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
 bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
 u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
@@ -575,6 +578,9 @@ void bfa_cb_rport_offline(void *rport);
 void bfa_cb_rport_qos_scn_flowid(void *rport,
                                 struct bfa_rport_qos_attr_s old_qos_attr,
                                 struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_scn_online(struct bfa_s *bfa);
+void bfa_cb_rport_scn_offline(struct bfa_s *bfa);
+void bfa_cb_rport_scn_no_dev(void *rp);
 void bfa_cb_rport_qos_scn_prio(void *rport,
                               struct bfa_rport_qos_attr_s old_qos_attr,
                               struct bfa_rport_qos_attr_s new_qos_attr);
index 0afa39076cef4e95f06c26f2c4e17916ed01c3d3..8ddd7e8be9779fd81ba7b5af30358ab3dd839a93 100644 (file)
@@ -888,16 +888,22 @@ bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-       if (cmd == IOCMD_RATELIM_ENABLE)
-               fcport->cfg.ratelimit = BFA_TRUE;
-       else if (cmd == IOCMD_RATELIM_DISABLE)
-               fcport->cfg.ratelimit = BFA_FALSE;
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               if (cmd == IOCMD_RATELIM_ENABLE)
+                       fcport->cfg.ratelimit = BFA_TRUE;
+               else if (cmd == IOCMD_RATELIM_DISABLE)
+                       fcport->cfg.ratelimit = BFA_FALSE;
 
-       if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
-               fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+               if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+                       fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+
+               iocmd->status = BFA_STATUS_OK;
+       }
 
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-       iocmd->status = BFA_STATUS_OK;
 
        return 0;
 }
@@ -919,8 +925,13 @@ bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
                return 0;
        }
 
-       fcport->cfg.trl_def_speed = iocmd->speed;
-       iocmd->status = BFA_STATUS_OK;
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               fcport->cfg.trl_def_speed = iocmd->speed;
+               iocmd->status = BFA_STATUS_OK;
+       }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
        return 0;
@@ -2161,22 +2172,28 @@ bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
 
-       if (v_cmd == IOCMD_TRUNK_ENABLE) {
-               trunk->attr.state = BFA_TRUNK_OFFLINE;
-               bfa_fcport_disable(&bfad->bfa);
-               fcport->cfg.trunked = BFA_TRUE;
-       } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
-               trunk->attr.state = BFA_TRUNK_DISABLED;
-               bfa_fcport_disable(&bfad->bfa);
-               fcport->cfg.trunked = BFA_FALSE;
-       }
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) ||
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               if (v_cmd == IOCMD_TRUNK_ENABLE) {
+                       trunk->attr.state = BFA_TRUNK_OFFLINE;
+                       bfa_fcport_disable(&bfad->bfa);
+                       fcport->cfg.trunked = BFA_TRUE;
+               } else if (v_cmd == IOCMD_TRUNK_DISABLE) {
+                       trunk->attr.state = BFA_TRUNK_DISABLED;
+                       bfa_fcport_disable(&bfad->bfa);
+                       fcport->cfg.trunked = BFA_FALSE;
+               }
+
+               if (!bfa_fcport_is_disabled(&bfad->bfa))
+                       bfa_fcport_enable(&bfad->bfa);
 
-       if (!bfa_fcport_is_disabled(&bfad->bfa))
-               bfa_fcport_enable(&bfad->bfa);
+               iocmd->status = BFA_STATUS_OK;
+       }
 
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2189,12 +2206,17 @@ bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd)
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
-               sizeof(struct bfa_trunk_attr_s));
-       iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) ||
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               memcpy((void *)&iocmd->attr, (void *)&trunk->attr,
+                       sizeof(struct bfa_trunk_attr_s));
+               iocmd->attr.port_id = bfa_lps_get_base_pid(&bfad->bfa);
+               iocmd->status = BFA_STATUS_OK;
+       }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2207,14 +2229,18 @@ bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
-               if (v_cmd == IOCMD_QOS_ENABLE)
-                       fcport->cfg.qos_enabled = BFA_TRUE;
-               else if (v_cmd == IOCMD_QOS_DISABLE)
-                       fcport->cfg.qos_enabled = BFA_FALSE;
+               if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+                       iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+               else {
+                       if (v_cmd == IOCMD_QOS_ENABLE)
+                               fcport->cfg.qos_enabled = BFA_TRUE;
+                       else if (v_cmd == IOCMD_QOS_DISABLE)
+                               fcport->cfg.qos_enabled = BFA_FALSE;
+               }
        }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2226,11 +2252,17 @@ bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd)
        unsigned long   flags;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       iocmd->attr.state = fcport->qos_attr.state;
-       iocmd->attr.total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else {
+               iocmd->attr.state = fcport->qos_attr.state;
+               iocmd->attr.total_bb_cr =
+                       be32_to_cpu(fcport->qos_attr.total_bb_cr);
+               iocmd->status = BFA_STATUS_OK;
+       }
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-       iocmd->status = BFA_STATUS_OK;
        return 0;
 }
 
@@ -2274,6 +2306,7 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
        struct bfad_hal_comp fcomp;
        unsigned long   flags;
        struct bfa_cb_pending_q_s cb_qe;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
 
        init_completion(&fcomp.comp);
        bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
@@ -2281,7 +2314,11 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
-       iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else
+               iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        if (iocmd->status != BFA_STATUS_OK) {
                bfa_trc(bfad, iocmd->status);
@@ -2300,6 +2337,7 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
        struct bfad_hal_comp fcomp;
        unsigned long   flags;
        struct bfa_cb_pending_q_s cb_qe;
+       struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
 
        init_completion(&fcomp.comp);
        bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
@@ -2307,7 +2345,11 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
        WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
-       iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
+       if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
+               (fcport->topology == BFA_PORT_TOPOLOGY_LOOP))
+               iocmd->status = BFA_STATUS_TOPOLOGY_LOOP;
+       else
+               iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
        if (iocmd->status != BFA_STATUS_OK) {
                bfa_trc(bfad, iocmd->status);
index d4220e13cafa09a4d8e90193e75514f691f596be..1f73db97fe24bb9e36411662d886f7ef59c00929 100644 (file)
@@ -499,6 +499,9 @@ enum bfi_rport_i2h_msgs {
        BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
        BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
        BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
+       BFI_RPORT_I2H_LIP_SCN_ONLINE =  BFA_I2HM(4),
+       BFI_RPORT_I2H_LIP_SCN_OFFLINE = BFA_I2HM(5),
+       BFI_RPORT_I2H_NO_DEV    = BFA_I2HM(6),
 };
 
 struct bfi_rport_create_req_s {
@@ -551,6 +554,14 @@ struct bfi_rport_qos_scn_s {
        struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
 };
 
+struct bfi_rport_lip_scn_s {
+       struct bfi_mhdr_s  mh;          /*!< common msg header  */
+       u16     bfa_handle;     /*!< host rport handle  */
+       u8              status;         /*!< scn online status  */
+       u8              rsvd;
+       struct bfa_fcport_loop_info_s   loop_info;
+};
+
 union bfi_rport_h2i_msg_u {
        struct bfi_msg_s                *msg;
        struct bfi_rport_create_req_s   *create_req;
@@ -563,6 +574,7 @@ union bfi_rport_i2h_msg_u {
        struct bfi_rport_create_rsp_s   *create_rsp;
        struct bfi_rport_delete_rsp_s   *delete_rsp;
        struct bfi_rport_qos_scn_s      *qos_scn_evt;
+       struct bfi_rport_lip_scn_s      *lip_scn;
 };
 
 /*
This page took 0.048337 seconds and 5 git commands to generate.