]> Pileus Git - ~andy/linux/blobdiff - include/scsi/libfc.h
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[~andy/linux] / include / scsi / libfc.h
index ef04a2c52b8c3335c4b7936be4e311a3846b7ef6..65dc9aacbf703b79874e32f8f61484a3e58856e9 100644 (file)
@@ -59,47 +59,41 @@ do {                                                                \
 
 #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),     \
+                        printk(KERN_INFO "host%u: disc: " fmt,         \
+                               (disc)->lport->host->host_no,           \
                                ##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;                     \
+#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),         \
+                        printk(KERN_INFO "host%u: fcp: %6x: " fmt,     \
+                               (pkt)->lp->host->host_no,               \
                                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))
-
 #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),        \
+                        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 *,
@@ -518,25 +526,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.
         *
@@ -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;
 
@@ -959,6 +954,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).
  *
@@ -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
@@ -1035,29 +1050,21 @@ 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_ */