[SCSI] libfc: change interface for rport_create
[safe/jmp/linux-2.6] / include / scsi / libfc.h
index ebdd9f4..d888cbe 100644 (file)
 
 #include <scsi/fc_frame.h>
 
-#define LIBFC_DEBUG
-
-#ifdef LIBFC_DEBUG
-/* Log messages */
-#define FC_DBG(fmt, args...)                                           \
-       do {                                                            \
-               printk(KERN_INFO "%s " fmt, __func__, ##args);          \
-       } while (0)
-#else
-#define FC_DBG(fmt, args...)
-#endif
+#define FC_LIBFC_LOGGING 0x01 /* General logging, not categorized */
+#define FC_LPORT_LOGGING 0x02 /* lport layer logging */
+#define FC_DISC_LOGGING  0x04 /* discovery layer logging */
+#define FC_RPORT_LOGGING 0x08 /* rport layer logging */
+#define FC_FCP_LOGGING   0x10 /* I/O path logging */
+#define FC_EM_LOGGING    0x20 /* Exchange Manager logging */
+#define FC_EXCH_LOGGING  0x40 /* Exchange/Sequence logging */
+#define FC_SCSI_LOGGING  0x80 /* SCSI logging (mostly error handling) */
+
+extern unsigned int fc_debug_logging;
+
+#define FC_CHECK_LOGGING(LEVEL, CMD)                           \
+do {                                                           \
+       if (unlikely(fc_debug_logging & LEVEL))                 \
+               do {                                            \
+                       CMD;                                    \
+               } while (0);                                    \
+} while (0)
+
+#define FC_LIBFC_DBG(fmt, args...)                                     \
+       FC_CHECK_LOGGING(FC_LIBFC_LOGGING,                              \
+                        printk(KERN_INFO "libfc: " fmt, ##args))
+
+#define FC_LPORT_DBG(lport, fmt, args...)                              \
+       FC_CHECK_LOGGING(FC_LPORT_LOGGING,                              \
+                        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 "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 "host%u: rport %6x: " fmt,    \
+                               (lport)->host->host_no,                 \
+                               (port_id), ##args))
+
+#define FC_RPORT_DBG(rport, fmt, args...)                              \
+do {                                                                   \
+       struct fc_rport_priv *rdata = rport->dd_data;                   \
+       struct fc_lport *lport = rdata->local_port;                     \
+       FC_RPORT_ID_DBG(lport, rport->port_id, fmt, ##args);            \
+} while (0)
+
+#define FC_FCP_DBG(pkt, fmt, args...)                                  \
+       FC_CHECK_LOGGING(FC_FCP_LOGGING,                                \
+                        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 "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 "host%u: scsi: " fmt,         \
+                               (lport)->host->host_no, ##args))
 
 /*
  * libfc error codes
  * 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,
@@ -88,13 +141,13 @@ 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 */
+       RPORT_ST_DELETE,        /* port being deleted */
 };
 
 enum fc_rport_trans_state {
@@ -124,6 +177,14 @@ enum fc_rport_event {
        RPORT_EV_LOGO
 };
 
+/*
+ * Temporary definition to prepare for split off from fc_rport_libfc_priv
+ * of a separately-allocated structure called fc_rport_priv.  This will
+ * be the primary object for the discovery and rport state machines.
+ * This definition is just to make this patch series easier to review.
+ */
+#define fc_rport_priv fc_rport_libfc_priv
+
 struct fc_rport_operations {
        void (*event_callback)(struct fc_lport *, struct fc_rport *,
                               enum fc_rport_event);
@@ -166,8 +227,6 @@ struct fc_rport_libfc_priv {
 #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;
@@ -289,6 +348,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.
@@ -313,6 +374,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 */
@@ -464,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.
         *
         * STATUS: OPTIONAL
@@ -524,7 +567,8 @@ struct libfc_function_template {
        /*
         * Create a remote port
         */
-       struct fc_rport *(*rport_create)(struct fc_disc_port *);
+       struct fc_rport *(*rport_create)(struct fc_lport *,
+                                        struct fc_rport_identifiers *);
 
        /*
         * Initiates the RP state machine. It is called from the LP module.
@@ -649,7 +693,7 @@ struct fc_lport {
 
        /* Associations */
        struct Scsi_Host        *host;
-       struct fc_exch_mgr      *emp;
+       struct list_head        ema_list;
        struct fc_rport         *dns_rp;
        struct fc_rport         *ptp_rp;
        void                    *scsi_priv;
@@ -905,6 +949,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
@@ -919,27 +985,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
@@ -981,28 +1045,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);