diff options
Diffstat (limited to 'include/scsi/libfc.h')
-rw-r--r-- | include/scsi/libfc.h | 244 |
1 files changed, 128 insertions, 116 deletions
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index b92584a8843..65dc9aacbf7 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -51,55 +51,49 @@ do { \ do { \ CMD; \ } while (0); \ -} while (0); +} while (0) #define FC_LIBFC_DBG(fmt, args...) \ FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \ - printk(KERN_INFO "libfc: " fmt, ##args);) + printk(KERN_INFO "libfc: " fmt, ##args)) #define FC_LPORT_DBG(lport, fmt, args...) \ FC_CHECK_LOGGING(FC_LPORT_LOGGING, \ - printk(KERN_INFO "lport: %6x: " fmt, \ - fc_host_port_id(lport->host), ##args);) + printk(KERN_INFO "host%u: lport %6x: " fmt, \ + (lport)->host->host_no, \ + fc_host_port_id((lport)->host), ##args)) #define FC_DISC_DBG(disc, fmt, args...) \ FC_CHECK_LOGGING(FC_DISC_LOGGING, \ - printk(KERN_INFO "disc: %6x: " fmt, \ - fc_host_port_id(disc->lport->host), \ - ##args);) - -#define FC_RPORT_DBG(rport, fmt, args...) \ -do { \ - struct fc_rport_libfc_priv *rdata = rport->dd_data; \ - struct fc_lport *lport = rdata->local_port; \ + printk(KERN_INFO "host%u: disc: " fmt, \ + (disc)->lport->host->host_no, \ + ##args)) + +#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \ FC_CHECK_LOGGING(FC_RPORT_LOGGING, \ - printk(KERN_INFO "rport: %6x: %6x: " fmt, \ - fc_host_port_id(lport->host), \ - rport->port_id, ##args);) \ -} while (0); + printk(KERN_INFO "host%u: rport %6x: " fmt, \ + (lport)->host->host_no, \ + (port_id), ##args)) + +#define FC_RPORT_DBG(rdata, fmt, args...) \ + FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args) #define FC_FCP_DBG(pkt, fmt, args...) \ FC_CHECK_LOGGING(FC_FCP_LOGGING, \ - printk(KERN_INFO "fcp: %6x: %6x: " fmt, \ - fc_host_port_id(pkt->lp->host), \ - pkt->rport->port_id, ##args);) - -#define FC_EM_DBG(em, fmt, args...) \ - FC_CHECK_LOGGING(FC_EM_LOGGING, \ - printk(KERN_INFO "em: %6x: " fmt, \ - fc_host_port_id(em->lp->host), \ - ##args);) + printk(KERN_INFO "host%u: fcp: %6x: " fmt, \ + (pkt)->lp->host->host_no, \ + pkt->rport->port_id, ##args)) #define FC_EXCH_DBG(exch, fmt, args...) \ FC_CHECK_LOGGING(FC_EXCH_LOGGING, \ - printk(KERN_INFO "exch: %6x: %4x: " fmt, \ - fc_host_port_id(exch->lp->host), \ - exch->xid, ##args);) + printk(KERN_INFO "host%u: xid %4x: " fmt, \ + (exch)->lp->host->host_no, \ + exch->xid, ##args)) #define FC_SCSI_DBG(lport, fmt, args...) \ FC_CHECK_LOGGING(FC_SCSI_LOGGING, \ - printk(KERN_INFO "scsi: %6x: " fmt, \ - fc_host_port_id(lport->host), ##args);) + printk(KERN_INFO "host%u: scsi: " fmt, \ + (lport)->host->host_no, ##args)) /* * libfc error codes @@ -125,7 +119,7 @@ do { \ * FC HBA status */ enum fc_lport_state { - LPORT_ST_NONE = 0, + LPORT_ST_DISABLED = 0, LPORT_ST_FLOGI, LPORT_ST_DNS, LPORT_ST_RPN_ID, @@ -143,53 +137,74 @@ enum fc_disc_event { }; enum fc_rport_state { - RPORT_ST_NONE = 0, RPORT_ST_INIT, /* initialized */ RPORT_ST_PLOGI, /* waiting for PLOGI completion */ RPORT_ST_PRLI, /* waiting for PRLI completion */ RPORT_ST_RTV, /* waiting for RTV completion */ RPORT_ST_READY, /* ready for use */ RPORT_ST_LOGO, /* port logout sent */ -}; - -enum fc_rport_trans_state { - FC_PORTSTATE_ROGUE, - FC_PORTSTATE_REAL, + RPORT_ST_ADISC, /* Discover Address sent */ + RPORT_ST_DELETE, /* port being deleted */ }; /** * struct fc_disc_port - temporary discovery port to hold rport identifiers - * @lp: Fibre Channel host port instance - * @peers: node for list management during discovery and RSCN processing - * @ids: identifiers structure to pass to fc_remote_port_add() - * @rport_work: work struct for starting the rport state machine + * @lp: Fibre Channel host port instance + * @peers: Node for list management during discovery and RSCN processing + * @rport_work: Work struct for starting the rport state machine + * @port_id: Port ID of the discovered port */ struct fc_disc_port { struct fc_lport *lp; struct list_head peers; - struct fc_rport_identifiers ids; struct work_struct rport_work; + u32 port_id; }; enum fc_rport_event { RPORT_EV_NONE = 0, - RPORT_EV_CREATED, + RPORT_EV_READY, RPORT_EV_FAILED, RPORT_EV_STOP, RPORT_EV_LOGO }; +struct fc_rport_priv; + struct fc_rport_operations { - void (*event_callback)(struct fc_lport *, struct fc_rport *, + void (*event_callback)(struct fc_lport *, struct fc_rport_priv *, enum fc_rport_event); }; /** * struct fc_rport_libfc_priv - libfc internal information about a remote port * @local_port: Fibre Channel host port instance + * @rp_state: indicates READY for I/O or DELETE when blocked. + * @flags: REC and RETRY supported flags + * @e_d_tov: error detect timeout value (in msec) + * @r_a_tov: resource allocation timeout value (in msec) + */ +struct fc_rport_libfc_priv { + struct fc_lport *local_port; + enum fc_rport_state rp_state; + u16 flags; + #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) + #define FC_RP_FLAGS_RETRY (1 << 1) + unsigned int e_d_tov; + unsigned int r_a_tov; +}; + +/** + * struct fc_rport_priv - libfc rport and discovery info about a remote port + * @local_port: Fibre Channel host port instance + * @rport: transport remote port + * @kref: reference counter * @rp_state: state tracks progress of PLOGI, PRLI, and RTV exchanges + * @ids: remote port identifiers and roles * @flags: REC and RETRY supported flags * @max_seq: maximum number of concurrent sequences + * @disc_id: discovery identifier + * @maxframe_size: maximum frame size * @retries: retry count in current state * @e_d_tov: error detect timeout value (in msec) * @r_a_tov: resource allocation timeout value (in msec) @@ -197,38 +212,28 @@ struct fc_rport_operations { * @retry_work: * @event_callback: Callback for rport READY, FAILED or LOGO */ -struct fc_rport_libfc_priv { +struct fc_rport_priv { struct fc_lport *local_port; + struct fc_rport *rport; + struct kref kref; enum fc_rport_state rp_state; + struct fc_rport_identifiers ids; u16 flags; - #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) - #define FC_RP_FLAGS_RETRY (1 << 1) u16 max_seq; + u16 disc_id; + u16 maxframe_size; unsigned int retries; unsigned int e_d_tov; unsigned int r_a_tov; - enum fc_rport_trans_state trans_state; struct mutex rp_mutex; struct delayed_work retry_work; enum fc_rport_event event; struct fc_rport_operations *ops; struct list_head peers; struct work_struct event_work; + u32 supported_classes; }; -#define PRIV_TO_RPORT(x) \ - (struct fc_rport *)((void *)x - sizeof(struct fc_rport)); -#define RPORT_TO_PRIV(x) \ - (struct fc_rport_libfc_priv *)((void *)x + sizeof(struct fc_rport)); - -struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *); - -static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64 wwnn) -{ - rport->node_name = wwnn; - rport->port_name = wwpn; -} - /* * fcoe stats structure */ @@ -344,6 +349,8 @@ static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp) */ struct fc_exch_mgr; +struct fc_exch_mgr_anchor; +extern u16 fc_cpu_mask; /* cpu mask for possible cpus */ /* * Sequence. @@ -368,6 +375,7 @@ struct fc_seq { */ struct fc_exch { struct fc_exch_mgr *em; /* exchange manager */ + struct fc_exch_pool *pool; /* per cpu exches pool */ u32 state; /* internal driver state */ u16 xid; /* our exchange ID */ struct list_head ex_list; /* free or busy list linkage */ @@ -415,7 +423,7 @@ struct libfc_function_template { * STATUS: OPTIONAL */ struct fc_seq *(*elsct_send)(struct fc_lport *lport, - struct fc_rport *rport, + u32 did, struct fc_frame *fp, unsigned int op, void (*resp)(struct fc_seq *, @@ -519,25 +527,6 @@ struct libfc_function_template { void (*exch_done)(struct fc_seq *sp); /* - * Assigns a EM and a free XID for an new exchange and then - * allocates a new exchange and sequence pair. - * The fp can be used to determine free XID. - * - * STATUS: OPTIONAL - */ - struct fc_exch *(*exch_get)(struct fc_lport *lp, struct fc_frame *fp); - - /* - * Release previously assigned XID by exch_get API. - * The LLD may implement this if XID is assigned by LLD - * in exch_get(). - * - * STATUS: OPTIONAL - */ - void (*exch_put)(struct fc_lport *lp, struct fc_exch_mgr *mp, - u16 ex_id); - - /* * Start a new sequence on the same exchange/sequence tuple. * * STATUS: OPTIONAL @@ -577,9 +566,11 @@ struct libfc_function_template { int (*lport_reset)(struct fc_lport *); /* - * Create a remote port + * Create a remote port with a given port ID + * + * STATUS: OPTIONAL */ - struct fc_rport *(*rport_create)(struct fc_disc_port *); + struct fc_rport_priv *(*rport_create)(struct fc_lport *, u32); /* * Initiates the RP state machine. It is called from the LP module. @@ -592,7 +583,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - int (*rport_login)(struct fc_rport *rport); + int (*rport_login)(struct fc_rport_priv *); /* * Logoff, and remove the rport from the transport if @@ -600,7 +591,7 @@ struct libfc_function_template { * * STATUS: OPTIONAL */ - int (*rport_logoff)(struct fc_rport *rport); + int (*rport_logoff)(struct fc_rport_priv *); /* * Recieve a request from a remote port. @@ -608,14 +599,20 @@ struct libfc_function_template { * STATUS: OPTIONAL */ void (*rport_recv_req)(struct fc_seq *, struct fc_frame *, - struct fc_rport *); + struct fc_lport *); /* * lookup an rport by it's port ID. * * STATUS: OPTIONAL */ - struct fc_rport *(*rport_lookup)(const struct fc_lport *, u32); + struct fc_rport_priv *(*rport_lookup)(const struct fc_lport *, u32); + + /* + * Destroy an rport after final kref_put(). + * The argument is a pointer to the kref inside the fc_rport_priv. + */ + void (*rport_destroy)(struct kref *); /* * Send a fcp cmd from fsp pkt. @@ -681,18 +678,16 @@ struct libfc_function_template { /* information used by the discovery layer */ struct fc_disc { unsigned char retry_count; - unsigned char delay; unsigned char pending; unsigned char requested; unsigned short seq_count; unsigned char buf_len; - enum fc_disc_event event; + u16 disc_id; void (*disc_callback)(struct fc_lport *, enum fc_disc_event); struct list_head rports; - struct list_head rogue_rports; struct fc_lport *lport; struct mutex disc_mutex; struct fc_gpn_ft_resp partial_buf; /* partial name buffer */ @@ -704,9 +699,9 @@ struct fc_lport { /* Associations */ struct Scsi_Host *host; - struct fc_exch_mgr *emp; - struct fc_rport *dns_rp; - struct fc_rport *ptp_rp; + struct list_head ema_list; + struct fc_rport_priv *dns_rp; + struct fc_rport_priv *ptp_rp; void *scsi_priv; struct fc_disc disc; @@ -960,6 +955,28 @@ int fc_elsct_init(struct fc_lport *lp); int fc_exch_init(struct fc_lport *lp); /* + * Adds Exchange Manager (EM) mp to lport. + * + * Adds specified mp to lport using struct fc_exch_mgr_anchor, + * the struct fc_exch_mgr_anchor allows same EM sharing by + * more than one lport with their specified match function, + * the match function is used in allocating exchange from + * added mp. + */ +struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport, + struct fc_exch_mgr *mp, + bool (*match)(struct fc_frame *)); + +/* + * Deletes Exchange Manager (EM) from lport by removing + * its anchor ema from lport. + * + * If removed anchor ema was the last user of its associated EM + * then also destroys associated EM. + */ +void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema); + +/* * Allocates an Exchange Manager (EM). * * The EM manages exchanges for their allocation and @@ -974,27 +991,25 @@ int fc_exch_init(struct fc_lport *lp); * a new exchange. * The LLD may choose to have multiple EMs, * e.g. one EM instance per CPU receive thread in LLD. - * The LLD can use exch_get() of struct libfc_function_template - * to specify XID for a new exchange within - * a specified EM instance. * - * The em_idx to uniquely identify an EM instance. + * Specified match function is used in allocating exchanges + * from newly allocated EM. */ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, enum fc_class class, u16 min_xid, - u16 max_xid); + u16 max_xid, + bool (*match)(struct fc_frame *)); /* - * Free an exchange manager. + * Free all exchange managers of a lport. */ -void fc_exch_mgr_free(struct fc_exch_mgr *mp); +void fc_exch_mgr_free(struct fc_lport *lport); /* * Receive a frame on specified local port and exchange manager. */ -void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp, - struct fc_frame *fp); +void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp); /* * This function is for exch_seq_send function pointer in @@ -1036,28 +1051,20 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec); void fc_exch_done(struct fc_seq *sp); /* - * Assigns a EM and XID for a frame and then allocates - * a new exchange and sequence pair. - * The fp can be used to determine free XID. - */ -struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp); - -/* * Allocate a new exchange and sequence pair. - * if ex_id is zero then next free exchange id - * from specified exchange manger mp will be assigned. */ -struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, - struct fc_frame *fp, u16 ex_id); +struct fc_exch *fc_exch_alloc(struct fc_lport *lport, struct fc_frame *fp); /* * Start a new sequence on the same exchange as the supplied sequence. */ struct fc_seq *fc_seq_start_next(struct fc_seq *sp); + /* - * Reset an exchange manager, completing all sequences and exchanges. - * If s_id is non-zero, reset only exchanges originating from that FID. - * If d_id is non-zero, reset only exchanges sending to that FID. + * Reset all EMs of a lport, releasing its all sequences and + * exchanges. If sid is non-zero, then reset only exchanges + * we sourced from that FID. If did is non-zero, reset only + * exchanges destined to that FID. */ void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id); @@ -1078,4 +1085,9 @@ void fc_destroy_exch_mgr(void); int fc_setup_rport(void); void fc_destroy_rport(void); +/* + * Internal libfc functions. + */ +const char *fc_els_resp_type(struct fc_frame *); + #endif /* _LIBFC_H_ */ |