summaryrefslogtreecommitdiffstats
path: root/include/scsi/libfc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/scsi/libfc.h')
-rw-r--r--include/scsi/libfc.h244
1 files changed, 128 insertions, 116 deletions
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index b92584a8843a..65dc9aacbf70 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_ */