/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright 2008 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. */ #ifndef _FNIC_FDLS_H_ #define _FNIC_FDLS_H_ #include "fnic_stats.h" #include "fdls_fc.h" /* FDLS - Fabric discovery and login services * -> VLAN discovery * -> retry every retry delay seconds until it succeeds. * <- List of VLANs * * -> Solicitation * <- Solicitation response (Advertisement) * * -> FCF selection & FLOGI ( FLOGI timeout - 2 * E_D_TOV) * <- FLOGI response * * -> FCF keep alive * <- FCF keep alive * * -> PLOGI to FFFFFC (DNS) (PLOGI timeout - 2 * R_A_TOV) * -> ABTS if timeout (ABTS tomeout - 2 * R_A_TOV) * <- PLOGI response * -> Retry PLOGI to FFFFFC (DNS) - Number of retries from vnic.cfg * * -> SCR to FFFFFC (DNS) (SCR timeout - 2 * R_A_TOV) * -> ABTS if timeout (ABTS tomeout - 2 * R_A_TOV) * <- SCR response * -> Retry SCR - Number of retries 2 * * -> GPN_FT to FFFFFC (GPN_FT timeout - 2 * R_A_TOV)a * -> Retry on BUSY until it succeeds * -> Retry on BUSY until it succeeds * -> 2 retries on timeout * * -> RFT_ID to FFFFFC (DNS) (RFT_ID timeout - 3 * R_A_TOV) * -> ABTS if timeout (ABTS tomeout - 2 * R_A_TOV) * -> Retry RFT_ID to FFFFFC (DNS) (Number of retries 2 ) * -> Ignore if both retires fail. * * Session establishment with targets * For each PWWN * -> PLOGI to FCID of that PWWN (PLOGI timeout 2 * R_A_TOV) * -> ABTS if timeout (ABTS tomeout - 2 * R_A_TOV) * <- PLOGI response * -> Retry PLOGI. Num retries using vnic.cfg * * -> PRLI to FCID of that PWWN (PRLI timeout 2 * R_A_TOV) * -> ABTS if timeout (ABTS tomeout - 2 * R_A_TOV) * <- PRLI response * -> Retry PRLI. Num retries using vnic.cfg * */ #define FDLS_RETRY_COUNT 2 /* * OXID encoding: * bits 0-8: oxid idx - allocated from poool * bits 9-13: oxid frame code from fnic_oxid_frame_type_e * bits 14-15: all zeros */ #define FNIC_OXID_POOL_SZ (512) /* always power of 2 */ #define FNIC_OXID_ENCODE(idx, frame_type) (frame_type | idx) #define FNIC_FRAME_MASK 0xFE00 #define FNIC_FRAME_TYPE(oxid) (oxid & FNIC_FRAME_MASK) #define FNIC_OXID_IDX(oxid) ((oxid) & (FNIC_OXID_POOL_SZ - 1)) #define OXID_RECLAIM_TOV(iport) (2 * iport->r_a_tov) /* in milliseconds */ #define FNIC_FDLS_FABRIC_ABORT_ISSUED 0x1 #define FNIC_FDLS_FPMA_LEARNT 0x2 /* tport flags */ #define FNIC_FDLS_TPORT_IN_GPN_FT_LIST 0x1 #define FNIC_FDLS_TGT_ABORT_ISSUED 0x2 #define FNIC_FDLS_TPORT_SEND_ADISC 0x4 #define FNIC_FDLS_RETRY_FRAME 0x8 #define FNIC_FDLS_TPORT_BUSY 0x10 #define FNIC_FDLS_TPORT_TERMINATING 0x20 #define FNIC_FDLS_TPORT_DELETED 0x40 #define FNIC_FDLS_SCSI_REGISTERED 0x200 /* Retry supported by rport(returned by prli service parameters) */ #define FDLS_FC_RP_FLAGS_RETRY 0x1 #define fdls_set_state(_fdls_fabric, _state) ((_fdls_fabric)->state = _state) #define fdls_get_state(_fdls_fabric) ((_fdls_fabric)->state) #define FNIC_FDMI_ACTIVE 0x8 #define FNIC_FIRST_LINK_UP 0x2 #define fdls_set_tport_state(_tport, _state) (_tport->state = _state) #define fdls_get_tport_state(_tport) (_tport->state) #define FNIC_PORTSPEED_10GBIT 1 #define FNIC_FRAME_HT_ROOM (2148) #define FNIC_FCOE_FRAME_MAXSZ (2112) #define FNIC_FRAME_TYPE_FABRIC_FLOGI 0x1000 #define FNIC_FRAME_TYPE_FABRIC_PLOGI 0x1200 #define FNIC_FRAME_TYPE_FABRIC_RPN 0x1400 #define FNIC_FRAME_TYPE_FABRIC_RFT 0x1600 #define FNIC_FRAME_TYPE_FABRIC_RFF 0x1800 #define FNIC_FRAME_TYPE_FABRIC_SCR 0x1A00 #define FNIC_FRAME_TYPE_FABRIC_GPN_FT 0x1C00 #define FNIC_FRAME_TYPE_FABRIC_LOGO 0x1E00 #define FNIC_FRAME_TYPE_FDMI_PLOGI 0x2000 #define FNIC_FRAME_TYPE_FDMI_RHBA 0x2200 #define FNIC_FRAME_TYPE_FDMI_RPA 0x2400 #define FNIC_FRAME_TYPE_TGT_PLOGI 0x2600 #define FNIC_FRAME_TYPE_TGT_PRLI 0x2800 #define FNIC_FRAME_TYPE_TGT_ADISC 0x2A00 #define FNIC_FRAME_TYPE_TGT_LOGO 0x2C00 struct fnic_fip_fcf_s { uint16_t vlan_id; uint8_t fcf_mac[6]; uint8_t fcf_priority; uint32_t fka_adv_period; uint8_t ka_disabled; }; enum fnic_fdls_state_e { FDLS_STATE_INIT = 0, FDLS_STATE_LINKDOWN, FDLS_STATE_FABRIC_LOGO, FDLS_STATE_FLOGO_DONE, FDLS_STATE_FABRIC_FLOGI, FDLS_STATE_FABRIC_PLOGI, FDLS_STATE_RPN_ID, FDLS_STATE_REGISTER_FC4_TYPES, FDLS_STATE_REGISTER_FC4_FEATURES, FDLS_STATE_SCR, FDLS_STATE_GPN_FT, FDLS_STATE_TGT_DISCOVERY, FDLS_STATE_RSCN_GPN_FT, FDLS_STATE_SEND_GPNFT }; struct fnic_fdls_fabric_s { enum fnic_fdls_state_e state; uint32_t flags; struct list_head tport_list; /* List of discovered tports */ struct timer_list retry_timer; int del_timer_inprogress; int del_fdmi_timer_inprogress; int retry_counter; int timer_pending; int fdmi_retry; struct timer_list fdmi_timer; int fdmi_pending; }; struct fnic_fdls_fip_s { uint32_t state; uint32_t flogi_retry; }; /* Message to tport_event_handler */ enum fnic_tgt_msg_id { TGT_EV_NONE = 0, TGT_EV_RPORT_ADD, TGT_EV_RPORT_DEL, TGT_EV_TPORT_DELETE, TGT_EV_REMOVE }; struct fnic_tport_event_s { struct list_head links; enum fnic_tgt_msg_id event; void *arg1; }; enum fdls_tgt_state_e { FDLS_TGT_STATE_INIT = 0, FDLS_TGT_STATE_PLOGI, FDLS_TGT_STATE_PRLI, FDLS_TGT_STATE_READY, FDLS_TGT_STATE_LOGO_RECEIVED, FDLS_TGT_STATE_ADISC, FDL_TGT_STATE_PLOGO, FDLS_TGT_STATE_OFFLINING, FDLS_TGT_STATE_OFFLINE }; struct fnic_tport_s { struct list_head links; /* To link the tports */ enum fdls_tgt_state_e state; uint32_t flags; uint32_t fcid; uint64_t wwpn; uint64_t wwnn; uint16_t active_oxid; uint16_t tgt_flags; atomic_t in_flight; /* io counter */ uint16_t max_payload_size; uint16_t r_a_tov; uint16_t e_d_tov; uint16_t lun0_delay; int max_concur_seqs; uint32_t fcp_csp; struct timer_list retry_timer; int del_timer_inprogress; int retry_counter; int timer_pending; unsigned int num_pending_cmds; int nexus_restart_count; int exch_reset_in_progress; void *iport; struct work_struct tport_del_work; struct completion *tport_del_done; struct fc_rport *rport; char str_wwpn[20]; char str_wwnn[20]; }; /* OXID pool related structures */ struct reclaim_entry_s { struct list_head links; /* oxid that needs to be freed after 2*r_a_tov */ uint16_t oxid_idx; /* in jiffies. Use this to waiting time */ unsigned long expires; unsigned long *bitmap; }; /* used for allocating oxids for fabric and fdmi requests */ struct fnic_oxid_pool_s { DECLARE_BITMAP(bitmap, FNIC_OXID_POOL_SZ); int sz; /* size of the pool or block */ int next_idx; /* used for cycling through the oxid pool */ /* retry schedule free */ DECLARE_BITMAP(pending_schedule_free, FNIC_OXID_POOL_SZ); struct delayed_work schedule_oxid_free_retry; /* List of oxids that need to be freed and reclaimed. * This list is shared by all the oxid pools */ struct list_head oxid_reclaim_list; /* Work associated with reclaim list */ struct delayed_work oxid_reclaim_work; }; /* iport */ enum fnic_iport_state_e { FNIC_IPORT_STATE_INIT = 0, FNIC_IPORT_STATE_LINK_WAIT, FNIC_IPORT_STATE_FIP, FNIC_IPORT_STATE_FABRIC_DISC, FNIC_IPORT_STATE_READY }; struct fnic_iport_s { enum fnic_iport_state_e state; struct fnic *fnic; uint64_t boot_time; uint32_t flags; int usefip; uint8_t hwmac[6]; /* HW MAC Addr */ uint8_t fpma[6]; /* Fabric Provided MA */ uint8_t fcfmac[6]; /* MAC addr of Fabric */ uint16_t vlan_id; uint32_t fcid; /* oxid pool */ struct fnic_oxid_pool_s oxid_pool; /* * fabric reqs are serialized and only one req at a time. * Tracking the oxid for sending abort */ uint16_t active_oxid_fabric_req; /* fdmi only */ uint16_t active_oxid_fdmi_plogi; uint16_t active_oxid_fdmi_rhba; uint16_t active_oxid_fdmi_rpa; struct fnic_fip_fcf_s selected_fcf; struct fnic_fdls_fip_s fip; struct fnic_fdls_fabric_s fabric; struct list_head tport_list; struct list_head tport_list_pending_del; /* list of tports for which we are yet to send PLOGO */ struct list_head inprocess_tport_list; struct list_head deleted_tport_list; struct work_struct tport_event_work; uint32_t e_d_tov; /* msec */ uint32_t r_a_tov; /* msec */ uint32_t link_supported_speeds; uint32_t max_flogi_retries; uint32_t max_plogi_retries; uint32_t plogi_timeout; uint32_t service_params; uint64_t wwpn; uint64_t wwnn; uint16_t max_payload_size; spinlock_t deleted_tport_lst_lock; struct completion *flogi_reg_done; struct fnic_iport_stats iport_stats; char str_wwpn[20]; char str_wwnn[20]; }; struct rport_dd_data_s { struct fnic_tport_s *tport; struct fnic_iport_s *iport; }; enum fnic_recv_frame_type_e { FNIC_FABRIC_FLOGI_RSP = 1, FNIC_FABRIC_PLOGI_RSP, FNIC_FABRIC_RPN_RSP, FNIC_FABRIC_RFT_RSP, FNIC_FABRIC_RFF_RSP, FNIC_FABRIC_SCR_RSP, FNIC_FABRIC_GPN_FT_RSP, FNIC_FABRIC_BLS_ABTS_RSP, FNIC_FDMI_PLOGI_RSP, FNIC_FDMI_REG_HBA_RSP, FNIC_FDMI_RPA_RSP, FNIC_FDMI_BLS_ABTS_RSP, FNIC_FABRIC_LOGO_RSP, /* responses to target requests */ FNIC_TPORT_PLOGI_RSP, FNIC_TPORT_PRLI_RSP, FNIC_TPORT_ADISC_RSP, FNIC_TPORT_BLS_ABTS_RSP, FNIC_TPORT_LOGO_RSP, /* unsolicited requests */ FNIC_BLS_ABTS_REQ, FNIC_ELS_PLOGI_REQ, FNIC_ELS_RSCN_REQ, FNIC_ELS_LOGO_REQ, FNIC_ELS_ECHO_REQ, FNIC_ELS_ADISC, FNIC_ELS_RLS, FNIC_ELS_RRQ, FNIC_ELS_UNSUPPORTED_REQ, }; enum fnic_port_speeds { DCEM_PORTSPEED_NONE = 0, DCEM_PORTSPEED_1G = 1000, DCEM_PORTSPEED_2G = 2000, DCEM_PORTSPEED_4G = 4000, DCEM_PORTSPEED_8G = 8000, DCEM_PORTSPEED_10G = 10000, DCEM_PORTSPEED_16G = 16000, DCEM_PORTSPEED_20G = 20000, DCEM_PORTSPEED_25G = 25000, DCEM_PORTSPEED_32G = 32000, DCEM_PORTSPEED_40G = 40000, DCEM_PORTSPEED_4x10G = 41000, DCEM_PORTSPEED_50G = 50000, DCEM_PORTSPEED_64G = 64000, DCEM_PORTSPEED_100G = 100000, DCEM_PORTSPEED_128G = 128000, }; /* Function Declarations */ /* fdls_disc.c */ void fnic_fdls_disc_init(struct fnic_iport_s *iport); void fnic_fdls_disc_start(struct fnic_iport_s *iport); void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame, int len, int fchdr_offset); void fnic_fdls_link_down(struct fnic_iport_s *iport); int fdls_init_frame_pool(struct fnic_iport_s *iport); uint8_t *fdls_alloc_frame(struct fnic_iport_s *iport); uint16_t fdls_alloc_oxid(struct fnic_iport_s *iport, int oxid_frame_type, uint16_t *active_oxid); void fdls_free_oxid(struct fnic_iport_s *iport, uint16_t oxid, uint16_t *active_oxid); void fdls_tgt_logout(struct fnic_iport_s *iport, struct fnic_tport_s *tport); void fnic_del_fabric_timer_sync(struct fnic *fnic); void fnic_del_tport_timer_sync(struct fnic *fnic, struct fnic_tport_s *tport); void fdls_send_fabric_logo(struct fnic_iport_s *iport); int fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport, struct fc_frame_header *fchdr); void fdls_send_tport_abts(struct fnic_iport_s *iport, struct fnic_tport_s *tport); bool fdls_delete_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport); void fdls_fdmi_timer_callback(struct timer_list *t); /* fnic_fcs.c */ void fnic_fdls_init(struct fnic *fnic, int usefip); void fnic_send_fcoe_frame(struct fnic_iport_s *iport, void *frame, int frame_size); void fnic_fcoe_send_vlan_req(struct fnic *fnic); int fnic_send_fip_frame(struct fnic_iport_s *iport, void *frame, int frame_size); void fnic_fdls_learn_fcoe_macs(struct fnic_iport_s *iport, void *rx_frame, uint8_t *fcid); void fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport, unsigned long flags); void fnic_fdls_remove_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport, unsigned long flags); /* fip.c */ void fnic_fcoe_send_vlan_req(struct fnic *fnic); void fnic_common_fip_cleanup(struct fnic *fnic); int fdls_fip_recv_frame(struct fnic *fnic, void *frame); void fnic_handle_fcs_ka_timer(struct timer_list *t); void fnic_handle_enode_ka_timer(struct timer_list *t); void fnic_handle_vn_ka_timer(struct timer_list *t); void fnic_handle_fip_timer(struct timer_list *t); extern void fdls_fabric_timer_callback(struct timer_list *t); /* fnic_scsi.c */ void fnic_scsi_fcpio_reset(struct fnic *fnic); extern void fdls_fabric_timer_callback(struct timer_list *t); void fnic_rport_exch_reset(struct fnic *fnic, u32 fcid); int fnic_fdls_register_portid(struct fnic_iport_s *iport, u32 port_id, void *fp); struct fnic_tport_s *fnic_find_tport_by_fcid(struct fnic_iport_s *iport, uint32_t fcid); struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport, uint64_t wwpn); #endif /* _FNIC_FDLS_H_ */