Commit 3a3b42bf authored by Robert Love's avatar Robert Love Committed by James Bottomley

[SCSI] libfc: Formatting cleanups across libfc

This patch makes a variety of cleanup changes to all libfc files.

This patch adds kernel-doc headers to all functions lacking them
and attempts to better format existing headers. It also add kernel-doc
headers to structures.

This patch ensures that the current naming conventions for local ports,
remote ports and remote port private data is upheld in the following
manner.

struct               instance (i.e. variable name)
--------------------------------------------------
fc_lport                      lport
fc_rport                      rport
fc_rport_libfc_priv           rpriv
fc_rport_priv                 rdata

I also renamed dns_rp and ptp_rp to dns_rdata and ptp_rdata
respectively.

I used emacs 'indent-region' and 'tabify' on all libfc files
to correct spacing alignments.

I feel sorry for anyone attempting to review this patch.
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent a51ab396
......@@ -53,8 +53,8 @@ static int fc_disc_single(struct fc_lport *, struct fc_disc_port *);
static void fc_disc_restart(struct fc_disc *);
/**
* fc_disc_stop_rports() - delete all the remote ports associated with the lport
* @disc: The discovery job to stop rports on
* fc_disc_stop_rports() - Delete all the remote ports associated with the lport
* @disc: The discovery job to stop remote ports on
*
* Locking Note: This function expects that the lport mutex is locked before
* calling it.
......@@ -74,9 +74,9 @@ void fc_disc_stop_rports(struct fc_disc *disc)
/**
* fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
* @sp: Current sequence of the RSCN exchange
* @fp: RSCN Frame
* @lport: Fibre Channel host port instance
* @sp: The sequence of the RSCN exchange
* @fp: The RSCN frame
* @lport: The local port that the request will be sent on
*
* Locking Note: This function expects that the disc_mutex is locked
* before it is called.
......@@ -185,9 +185,9 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_disc_recv_req() - Handle incoming requests
* @sp: Current sequence of the request exchange
* @fp: The frame
* @lport: The FC local port
* @sp: The sequence of the request exchange
* @fp: The request frame
* @lport: The local port receiving the request
*
* Locking Note: This function is called from the EM and will lock
* the disc_mutex before calling the handler for the
......@@ -215,7 +215,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_disc_restart() - Restart discovery
* @lport: FC discovery context
* @disc: The discovery object to be restarted
*
* Locking Note: This function expects that the disc mutex
* is already locked.
......@@ -242,9 +242,9 @@ static void fc_disc_restart(struct fc_disc *disc)
}
/**
* fc_disc_start() - Fibre Channel Target discovery
* @lport: FC local port
* @disc_callback: function to be called when discovery is complete
* fc_disc_start() - Start discovery on a local port
* @lport: The local port to have discovery started on
* @disc_callback: Callback function to be called when discovery is complete
*/
static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
enum fc_disc_event),
......@@ -265,8 +265,8 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
/**
* fc_disc_done() - Discovery has been completed
* @disc: FC discovery context
* @event: discovery completion status
* @disc: The discovery context
* @event: The discovery completion status
*
* Locking Note: This function expects that the disc mutex is locked before
* it is called. The discovery callback is then made with the lock released,
......@@ -307,8 +307,8 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event)
/**
* fc_disc_error() - Handle error on dNS request
* @disc: FC discovery context
* @fp: The frame pointer
* @disc: The discovery context
* @fp: The error code encoded as a frame pointer
*/
static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
{
......@@ -344,7 +344,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
/**
* fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
* @lport: FC discovery context
* @lport: The discovery context
*
* Locking Note: This function expects that the disc_mutex is locked
* before it is called.
......@@ -378,9 +378,9 @@ static void fc_disc_gpn_ft_req(struct fc_disc *disc)
/**
* fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
* @lport: Fibre Channel host port instance
* @buf: GPN_FT response buffer
* @len: size of response buffer
* @lport: The local port the GPN_FT was received on
* @buf: The GPN_FT response buffer
* @len: The size of response buffer
*
* Goes through the list of IDs and names resulting from a request.
*/
......@@ -479,10 +479,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
}
/**
* fc_disc_timeout() - Retry handler for the disc component
* @work: Structure holding disc obj that needs retry discovery
*
* Handle retry of memory allocation for remote ports.
* fc_disc_timeout() - Handler for discovery timeouts
* @work: Structure holding discovery context that needs to retry discovery
*/
static void fc_disc_timeout(struct work_struct *work)
{
......@@ -496,9 +494,9 @@ static void fc_disc_timeout(struct work_struct *work)
/**
* fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
* @sp: Current sequence of GPN_FT exchange
* @fp: response frame
* @lp_arg: Fibre Channel host port instance
* @sp: The sequence that the GPN_FT response was received on
* @fp: The GPN_FT response frame
* @lp_arg: The discovery context
*
* Locking Note: This function is called without disc mutex held, and
* should do all its processing with the mutex held
......@@ -569,9 +567,9 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_disc_gpn_id_resp() - Handle a response frame from Get Port Names (GPN_ID)
* @sp: exchange sequence
* @fp: response frame
* @rdata_arg: remote port private data
* @sp: The sequence the GPN_ID is on
* @fp: The response frame
* @rdata_arg: The remote port that sent the GPN_ID response
*
* Locking Note: This function is called without disc mutex held.
*/
......@@ -639,7 +637,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_disc_gpn_id_req() - Send Get Port Names by ID (GPN_ID) request
* @lport: local port
* @lport: The local port to initiate discovery on
* @rdata: remote port private data
*
* Locking Note: This function expects that the disc_mutex is locked
......@@ -664,7 +662,7 @@ static int fc_disc_gpn_id_req(struct fc_lport *lport,
/**
* fc_disc_single() - Discover the directory information for a single target
* @lport: local port
* @lport: The local port the remote port is associated with
* @dp: The port to rediscover
*
* Locking Note: This function expects that the disc_mutex is locked
......@@ -683,7 +681,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
/**
* fc_disc_stop() - Stop discovery for a given lport
* @lport: The lport that discovery should stop for
* @lport: The local port that discovery should stop on
*/
void fc_disc_stop(struct fc_lport *lport)
{
......@@ -697,7 +695,7 @@ void fc_disc_stop(struct fc_lport *lport)
/**
* fc_disc_stop_final() - Stop discovery for a given lport
* @lport: The lport that discovery should stop for
* @lport: The lport that discovery should stop on
*
* This function will block until discovery has been
* completely stopped and all rports have been deleted.
......@@ -709,8 +707,8 @@ void fc_disc_stop_final(struct fc_lport *lport)
}
/**
* fc_disc_init() - Initialize the discovery block
* @lport: FC local port
* fc_disc_init() - Initialize the discovery layer for a local port
* @lport: The local port that needs the discovery layer to be initialized
*/
int fc_disc_init(struct fc_lport *lport)
{
......
......@@ -28,16 +28,21 @@
#include <scsi/libfc.h>
#include <scsi/fc_encode.h>
/*
* fc_elsct_send - sends ELS/CT frame
/**
* fc_elsct_send() - Send an ELS or CT frame
* @lport: The local port to send the frame on
* @did: The destination ID for the frame
* @fp: The frame to be sent
* @op: The operational code
* @resp: The callback routine when the response is received
* @arg: The argument to pass to the response callback routine
* @timer_msec: The timeout period for the frame (in msecs)
*/
struct fc_seq *fc_elsct_send(struct fc_lport *lport,
u32 did,
struct fc_frame *fp,
unsigned int op,
struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did,
struct fc_frame *fp, unsigned int op,
void (*resp)(struct fc_seq *,
struct fc_frame *fp,
void *arg),
struct fc_frame *,
void *),
void *arg, u32 timer_msec)
{
enum fc_rctl r_ctl;
......@@ -65,6 +70,10 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport,
}
EXPORT_SYMBOL(fc_elsct_send);
/**
* fc_elsct_init() - Initialize the ELS/CT layer
* @lport: The local port to initialize the ELS/CT layer for
*/
int fc_elsct_init(struct fc_lport *lport)
{
if (!lport->tt.elsct_send)
......@@ -75,8 +84,8 @@ int fc_elsct_init(struct fc_lport *lport)
EXPORT_SYMBOL(fc_elsct_init);
/**
* fc_els_resp_type() - return string describing ELS response for debug.
* @fp: frame pointer with possible error code.
* fc_els_resp_type() - Return a string describing the ELS response
* @fp: The frame pointer or possible error code
*/
const char *fc_els_resp_type(struct fc_frame *fp)
{
......
......@@ -52,34 +52,46 @@ static struct kmem_cache *fc_em_cachep; /* cache for exchanges */
* fc_seq holds the state for an individual sequence.
*/
/*
* Per cpu exchange pool
/**
* struct fc_exch_pool - Per cpu exchange pool
* @next_index: Next possible free exchange index
* @total_exches: Total allocated exchanges
* @lock: Exch pool lock
* @ex_list: List of exchanges
*
* This structure manages per cpu exchanges in array of exchange pointers.
* This array is allocated followed by struct fc_exch_pool memory for
* assigned range of exchanges to per cpu pool.
*/
struct fc_exch_pool {
u16 next_index; /* next possible free exchange index */
u16 total_exches; /* total allocated exchanges */
spinlock_t lock; /* exch pool lock */
struct list_head ex_list; /* allocated exchanges list */
u16 next_index;
u16 total_exches;
spinlock_t lock;
struct list_head ex_list;
};
/*
* Exchange manager.
/**
* struct fc_exch_mgr - The Exchange Manager (EM).
* @class: Default class for new sequences
* @kref: Reference counter
* @min_xid: Minimum exchange ID
* @max_xid: Maximum exchange ID
* @ep_pool: Reserved exchange pointers
* @pool_max_index: Max exch array index in exch pool
* @pool: Per cpu exch pool
* @stats: Statistics structure
*
* This structure is the center for creating exchanges and sequences.
* It manages the allocation of exchange IDs.
*/
struct fc_exch_mgr {
enum fc_class class; /* default class for sequences */
struct kref kref; /* exchange mgr reference count */
u16 min_xid; /* min exchange ID */
u16 max_xid; /* max exchange ID */
mempool_t *ep_pool; /* reserve ep's */
u16 pool_max_index; /* max exch array index in exch pool */
struct fc_exch_pool *pool; /* per cpu exch pool */
enum fc_class class;
struct kref kref;
u16 min_xid;
u16 max_xid;
mempool_t *ep_pool;
u16 pool_max_index;
struct fc_exch_pool *pool;
/*
* currently exchange mgr stats are updated but not used.
......@@ -97,6 +109,18 @@ struct fc_exch_mgr {
};
#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
/**
* struct fc_exch_mgr_anchor - primary structure for list of EMs
* @ema_list: Exchange Manager Anchor list
* @mp: Exchange Manager associated with this anchor
* @match: Routine to determine if this anchor's EM should be used
*
* When walking the list of anchors the match routine will be called
* for each anchor to determine if that EM should be used. The last
* anchor in the list will always match to handle any exchanges not
* handled by other EMs. The non-default EMs would be added to the
* anchor list by HW that provides FCoE offloads.
*/
struct fc_exch_mgr_anchor {
struct list_head ema_list;
struct fc_exch_mgr *mp;
......@@ -196,6 +220,15 @@ static char *fc_exch_rctl_names[] = FC_RCTL_NAMES_INIT;
#define FC_TABLE_SIZE(x) (sizeof(x) / sizeof(x[0]))
/**
* fc_exch_name_lookup() - Lookup name by opcode
* @op: Opcode to be looked up
* @table: Opcode/name table
* @max_index: Index not to be exceeded
*
* This routine is used to determine a human-readable string identifying
* a R_CTL opcode.
*/
static inline const char *fc_exch_name_lookup(unsigned int op, char **table,
unsigned int max_index)
{
......@@ -208,25 +241,34 @@ static inline const char *fc_exch_name_lookup(unsigned int op, char **table,
return name;
}
/**
* fc_exch_rctl_name() - Wrapper routine for fc_exch_name_lookup()
* @op: The opcode to be looked up
*/
static const char *fc_exch_rctl_name(unsigned int op)
{
return fc_exch_name_lookup(op, fc_exch_rctl_names,
FC_TABLE_SIZE(fc_exch_rctl_names));
}
/*
* Hold an exchange - keep it from being freed.
/**
* fc_exch_hold() - Increment an exchange's reference count
* @ep: Echange to be held
*/
static void fc_exch_hold(struct fc_exch *ep)
static inline void fc_exch_hold(struct fc_exch *ep)
{
atomic_inc(&ep->ex_refcnt);
}
/*
* setup fc hdr by initializing few more FC header fields and sof/eof.
* Initialized fields by this func:
* - fh_ox_id, fh_rx_id, fh_seq_id, fh_seq_cnt
* - sof and eof
/**
* fc_exch_setup_hdr() - Initialize a FC header by initializing some fields
* and determine SOF and EOF.
* @ep: The exchange to that will use the header
* @fp: The frame whose header is to be modified
* @f_ctl: F_CTL bits that will be used for the frame header
*
* The fields initialized by this routine are: fh_ox_id, fh_rx_id,
* fh_seq_id, fh_seq_cnt and the SOF and EOF.
*/
static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp,
u32 f_ctl)
......@@ -243,7 +285,7 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp,
if (fc_sof_needs_ack(ep->class))
fr_eof(fp) = FC_EOF_N;
/*
* Form f_ctl.
* From F_CTL.
* The number of fill bytes to make the length a 4-byte
* multiple is the low order 2-bits of the f_ctl.
* The fill itself will have been cleared by the frame
......@@ -273,9 +315,12 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp,
fh->fh_seq_cnt = htons(ep->seq.cnt);
}
/*
* Release a reference to an exchange.
* If the refcnt goes to zero and the exchange is complete, it is freed.
/**
* fc_exch_release() - Decrement an exchange's reference count
* @ep: Exchange to be released
*
* If the reference count reaches zero and the exchange is complete,
* it is freed.
*/
static void fc_exch_release(struct fc_exch *ep)
{
......@@ -290,6 +335,10 @@ static void fc_exch_release(struct fc_exch *ep)
}
}
/**
* fc_exch_done_locked() - Complete an exchange with the exchange lock held
* @ep: The exchange that is complete
*/
static int fc_exch_done_locked(struct fc_exch *ep)
{
int rc = 1;
......@@ -314,6 +363,15 @@ static int fc_exch_done_locked(struct fc_exch *ep)
return rc;
}
/**
* fc_exch_ptr_get() - Return an exchange from an exchange pool
* @pool: Exchange Pool to get an exchange from
* @index: Index of the exchange within the pool
*
* Use the index to get an exchange from within an exchange pool. exches
* will point to an array of exchange pointers. The index will select
* the exchange within the array.
*/
static inline struct fc_exch *fc_exch_ptr_get(struct fc_exch_pool *pool,
u16 index)
{
......@@ -321,12 +379,22 @@ static inline struct fc_exch *fc_exch_ptr_get(struct fc_exch_pool *pool,
return exches[index];
}
/**
* fc_exch_ptr_set() - Assign an exchange to a slot in an exchange pool
* @pool: The pool to assign the exchange to
* @index: The index in the pool where the exchange will be assigned
* @ep: The exchange to assign to the pool
*/
static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
struct fc_exch *ep)
{
((struct fc_exch **)(pool + 1))[index] = ep;
}
/**
* fc_exch_delete() - Delete an exchange
* @ep: The exchange to be deleted
*/
static void fc_exch_delete(struct fc_exch *ep)
{
struct fc_exch_pool *pool;
......@@ -342,8 +410,14 @@ static void fc_exch_delete(struct fc_exch *ep)
fc_exch_release(ep); /* drop hold for exch in mp */
}
/*
* Internal version of fc_exch_timer_set - used with lock held.
/**
* fc_exch_timer_set_locked() - Start a timer for an exchange w/ the
* the exchange lock held
* @ep: The exchange whose timer will start
* @timer_msec: The timeout period
*
* Used for upper level protocols to time out the exchange.
* The timer is cancelled when it fires or when the exchange completes.
*/
static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
unsigned int timer_msec)
......@@ -358,12 +432,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
fc_exch_hold(ep); /* hold for timer */
}
/*
* Set timer for an exchange.
* The time is a minimum delay in milliseconds until the timer fires.
* Used for upper level protocols to time out the exchange.
* The timer is cancelled when it fires or when the exchange completes.
* Returns non-zero if a timer couldn't be allocated.
/**
* fc_exch_timer_set() - Lock the exchange and set the timer
* @ep: The exchange whose timer will start
* @timer_msec: The timeout period
*/
static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec)
{
......@@ -373,9 +445,12 @@ static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec)
}
/**
* send a frame using existing sequence and exchange.
* fc_seq_send() - Send a frame using existing sequence/exchange pair
* @lport: The local port that the exchange will be sent on
* @sp: The sequence to be sent
* @fp: The frame to be sent on the exchange
*/
static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp,
static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
struct fc_frame *fp)
{
struct fc_exch *ep;
......@@ -403,7 +478,7 @@ static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp,
/*
* Send the frame.
*/
error = lp->tt.frame_send(lp, fp);
error = lport->tt.frame_send(lport, fp);
/*
* Update the exchange and sequence flags,
......@@ -419,9 +494,9 @@ static int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp,
}
/**
* fc_seq_alloc() - Allocate a sequence.
* @ep: Exchange pointer
* @seq_id: Sequence ID to allocate a sequence for
* fc_seq_alloc() - Allocate a sequence for a given exchange
* @ep: The exchange to allocate a new sequence for
* @seq_id: The sequence ID to be used
*
* We don't support multiple originated sequences on the same exchange.
* By implication, any previously originated sequence on this exchange
......@@ -438,6 +513,11 @@ static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id)
return sp;
}
/**
* fc_seq_start_next_locked() - Allocate a new sequence on the same
* exchange as the supplied sequence
* @sp: The sequence/exchange to get a new sequence for
*/
static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp)
{
struct fc_exch *ep = fc_seq_exch(sp);
......@@ -449,8 +529,9 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp)
}
/**
* Allocate a new sequence on the same exchange as the supplied sequence.
* This will never return NULL.
* fc_seq_start_next() - Lock the exchange and get a new sequence
* for a given sequence/exchange pair
* @sp: The sequence/exchange to get a new exchange for
*/
static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
{
......@@ -464,9 +545,11 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
}
/**
* This function is for seq_exch_abort function pointer in
* struct libfc_function_template, see comment block on
* seq_exch_abort for description of this function.
* fc_seq_exch_abort() - Abort an exchange and sequence
* @req_sp: The sequence to be aborted
* @timer_msec: The period of time to wait before aborting
*
* Generally called because of a timeout or an abort from the upper layer.
*/
static int fc_seq_exch_abort(const struct fc_seq *req_sp,
unsigned int timer_msec)
......@@ -519,9 +602,9 @@ static int fc_seq_exch_abort(const struct fc_seq *req_sp,
return error;
}
/*
* Exchange timeout - handle exchange timer expiration.
* The timer will have been cancelled before this is called.
/**
* fc_exch_timeout() - Handle exchange timer expiration
* @work: The work_struct identifying the exchange that timed out
*/
static void fc_exch_timeout(struct work_struct *work)
{
......@@ -570,9 +653,9 @@ static void fc_exch_timeout(struct work_struct *work)
}
/**
* fc_exch_em_alloc() - allocate an exchange from a specified EM.
* @lport: ptr to the local port
* @mp: ptr to the exchange manager
* fc_exch_em_alloc() - Allocate an exchange from a specified EM.
* @lport: The local port that the exchange is for
* @mp: The exchange manager that will allocate the exchange
*
* Returns pointer to allocated fc_exch with exch lock held.
*/
......@@ -640,14 +723,15 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
}
/**
* fc_exch_alloc() - allocate an exchange.
* @lport: ptr to the local port
* @fp: ptr to the FC frame
* fc_exch_alloc() - Allocate an exchange from an EM on a
* local port's list of EMs.
* @lport: The local port that will own the exchange
* @fp: The FC frame that the exchange will be for
*
* This function walks the list of the exchange manager(EM)
* anchors to select a EM for new exchange allocation. The
* EM is selected having either a NULL match function pointer
* or call to match function returning true.
* This function walks the list of exchange manager(EM)
* anchors to select an EM for a new exchange allocation. The
* EM is selected when a NULL match function pointer is encountered
* or when a call to a match function returns true.
*/
static struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
struct fc_frame *fp)
......@@ -665,8 +749,10 @@ static struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
return NULL;
}
/*
* Lookup and hold an exchange.
/**
* fc_exch_find() - Lookup and hold an exchange
* @mp: The exchange manager to lookup the exchange from
* @xid: The XID of the exchange to look up
*/
static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
{
......@@ -690,7 +776,7 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
/**
* fc_exch_done() - Indicate that an exchange/sequence tuple is complete and
* the memory allocated for the related objects may be freed.
* @sp: Sequence pointer
* @sp: The sequence that has completed
*/
static void fc_exch_done(struct fc_seq *sp)
{
......@@ -704,8 +790,12 @@ static void fc_exch_done(struct fc_seq *sp)
fc_exch_delete(ep);
}
/*
* Allocate a new exchange as responder.
/**
* fc_exch_resp() - Allocate a new exchange for a response frame
* @lport: The local port that the exchange was for
* @mp: The exchange manager to allocate the exchange from
* @fp: The response frame
*
* Sets the responder ID in the frame header.
*/
static struct fc_exch *fc_exch_resp(struct fc_lport *lport,
......@@ -746,8 +836,13 @@ static struct fc_exch *fc_exch_resp(struct fc_lport *lport,
return ep;
}
/*
* Find a sequence for receive where the other end is originating the sequence.
/**
* fc_seq_lookup_recip() - Find a sequence where the other end
* originated the sequence
* @lport: The local port that the frame was sent to
* @mp: The Exchange Manager to lookup the exchange from
* @fp: The frame associated with the sequence we're looking for
*
* If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
* on the ep that should be released by the caller.
*/
......@@ -853,10 +948,12 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
return reject;
}
/*
* Find the sequence for a frame being received.
* We originated the sequence, so it should be found.
* We may or may not have originated the exchange.
/**
* fc_seq_lookup_orig() - Find a sequence where this end
* originated the sequence
* @mp: The Exchange Manager to lookup the exchange from
* @fp: The frame associated with the sequence we're looking for
*
* Does not hold the sequence for the caller.
*/
static struct fc_seq *fc_seq_lookup_orig(struct fc_exch_mgr *mp,
......@@ -888,8 +985,12 @@ static struct fc_seq *fc_seq_lookup_orig(struct fc_exch_mgr *mp,
return sp;
}
/*
* Set addresses for an exchange.
/**
* fc_exch_set_addr() - Set the source and destination IDs for an exchange
* @ep: The exchange to set the addresses for
* @orig_id: The originator's ID
* @resp_id: The responder's ID
*
* Note this must be done before the first sequence of the exchange is sent.
*/
static void fc_exch_set_addr(struct fc_exch *ep,
......@@ -906,11 +1007,11 @@ static void fc_exch_set_addr(struct fc_exch *ep,
}
/**
* fc_seq_els_rsp_send() - Send ELS response using mainly infomation
* in exchange and sequence in EM layer.
* @sp: Sequence pointer
* @els_cmd: ELS command
* @els_data: ELS data
* fc_seq_els_rsp_send() - Send an ELS response using infomation from
* the existing sequence/exchange.
* @sp: The sequence/exchange to get information from
* @els_cmd: The ELS command to be sent
* @els_data: The ELS data to be sent
*/
static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd,
struct fc_seq_els_data *els_data)
......@@ -933,8 +1034,12 @@ static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd,
}
}
/*
* Send a sequence, which is also the last sequence in the exchange.
/**
* fc_seq_send_last() - Send a sequence that is the last in the exchange
* @sp: The sequence that is to be sent
* @fp: The frame that will be sent on the sequence
* @rctl: The R_CTL information to be sent
* @fh_type: The frame header type
*/
static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp,
enum fc_rctl rctl, enum fc_fh_type fh_type)
......@@ -948,9 +1053,12 @@ static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp,
fc_seq_send(ep->lp, sp, fp);
}
/*
/**
* fc_seq_send_ack() - Send an acknowledgement that we've received a frame
* @sp: The sequence to send the ACK on
* @rx_fp: The received frame that is being acknoledged
*
* Send ACK_1 (or equiv.) indicating we received something.
* The frame we're acking is supplied.
*/
static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
{
......@@ -958,14 +1066,14 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
struct fc_frame_header *rx_fh;
struct fc_frame_header *fh;
struct fc_exch *ep = fc_seq_exch(sp);
struct fc_lport *lp = ep->lp;
struct fc_lport *lport = ep->lp;
unsigned int f_ctl;
/*
* Don't send ACKs for class 3.
*/
if (fc_sof_needs_ack(fr_sof(rx_fp))) {
fp = fc_frame_alloc(lp, 0);
fp = fc_frame_alloc(lport, 0);
if (!fp)
return;
......@@ -1000,12 +1108,16 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
else
fr_eof(fp) = FC_EOF_N;
(void) lp->tt.frame_send(lp, fp);
lport->tt.frame_send(lport, fp);
}
}
/*
* Send BLS Reject.
/**
* fc_exch_send_ba_rjt() - Send BLS Reject
* @rx_fp: The frame being rejected
* @reason: The reason the frame is being rejected
* @explan: The explaination for the rejection
*
* This is for rejecting BA_ABTS only.
*/
static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
......@@ -1016,11 +1128,11 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
struct fc_frame_header *rx_fh;
struct fc_frame_header *fh;
struct fc_ba_rjt *rp;
struct fc_lport *lp;
struct fc_lport *lport;
unsigned int f_ctl;
lp = fr_dev(rx_fp);
fp = fc_frame_alloc(lp, sizeof(*rp));
lport = fr_dev(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*rp));
if (!fp)
return;
fh = fc_frame_header_get(fp);
......@@ -1065,13 +1177,17 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
if (fc_sof_needs_ack(fr_sof(fp)))
fr_eof(fp) = FC_EOF_N;
(void) lp->tt.frame_send(lp, fp);
lport->tt.frame_send(lport, fp);
}
/*
* Handle an incoming ABTS. This would be for target mode usually,
* but could be due to lost FCP transfer ready, confirm or RRQ.
* We always handle this as an exchange abort, ignoring the parameter.
/**
* fc_exch_recv_abts() - Handle an incoming ABTS
* @ep: The exchange the abort was on
* @rx_fp: The ABTS frame
*
* This would be for target mode usually, but could be due to lost
* FCP transfer ready, confirm or RRQ. We always handle this as an
* exchange abort, ignoring the parameter.
*/
static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
{
......@@ -1120,10 +1236,14 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
fc_frame_free(rx_fp);
}
/*
* Handle receive where the other end is originating the sequence.
/**
* fc_exch_recv_req() - Handler for an incoming request where is other
* end is originating the sequence
* @lport: The local port that received the request
* @mp: The EM that the exchange is on
* @fp: The request frame
*/
static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
struct fc_frame *fp)
{
struct fc_frame_header *fh = fc_frame_header_get(fp);
......@@ -1137,14 +1257,14 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
/* We can have the wrong fc_lport at this point with NPIV, which is a
* problem now that we know a new exchange needs to be allocated
*/
lp = fc_vport_id_lookup(lp, ntoh24(fh->fh_d_id));
if (!lp) {
lport = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
if (!lport) {
fc_frame_free(fp);
return;
}
fr_seq(fp) = NULL;
reject = fc_seq_lookup_recip(lp, mp, fp);
reject = fc_seq_lookup_recip(lport, mp, fp);
if (reject == FC_RJT_NONE) {
sp = fr_seq(fp); /* sequence will be held */
ep = fc_seq_exch(sp);
......@@ -1167,17 +1287,21 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
if (ep->resp)
ep->resp(sp, fp, ep->arg);
else
lp->tt.lport_recv(lp, sp, fp);
lport->tt.lport_recv(lport, sp, fp);
fc_exch_release(ep); /* release from lookup */
} else {
FC_LPORT_DBG(lp, "exch/seq lookup failed: reject %x\n", reject);
FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n",
reject);
fc_frame_free(fp);
}
}
/*
* Handle receive where the other end is originating the sequence in
* response to our exchange.
/**
* fc_exch_recv_seq_resp() - Handler for an incoming response where the other
* end is the originator of the sequence that is a
* response to our initial exchange
* @mp: The EM that the exchange is on
* @fp: The response frame
*/
static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
{
......@@ -1268,8 +1392,11 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
fc_frame_free(fp);
}
/*
* Handle receive for a sequence where other end is responding to our sequence.
/**
* fc_exch_recv_resp() - Handler for a sequence where other end is
* responding to our sequence
* @mp: The EM that the exchange is on
* @fp: The response frame
*/
static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
{
......@@ -1285,9 +1412,13 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
fc_frame_free(fp);
}
/*
* Handle the response to an ABTS for exchange or sequence.
* This can be BA_ACC or BA_RJT.
/**
* fc_exch_abts_resp() - Handler for a response to an ABT
* @ep: The exchange that the frame is on
* @fp: The response frame
*
* This response would be to an ABTS cancelling an exchange or sequence.
* The response can be either BA_ACC or BA_RJT
*/
static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
{
......@@ -1362,9 +1493,12 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
}
/*
* Receive BLS sequence.
* This is always a sequence initiated by the remote side.
/**
* fc_exch_recv_bls() - Handler for a BLS sequence
* @mp: The EM that the exchange is on
* @fp: The request frame
*
* The BLS frame is always a sequence initiated by the remote side.
* We may be either the originator or recipient of the exchange.
*/
static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
......@@ -1421,8 +1555,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
fc_exch_release(ep); /* release hold taken by fc_exch_find */
}
/*
* Accept sequence with LS_ACC.
/**
* fc_seq_ls_acc() - Accept sequence with LS_ACC
* @req_sp: The request sequence
*
* If this fails due to allocation or transmit congestion, assume the
* originator will repeat the sequence.
*/
......@@ -1442,8 +1578,12 @@ static void fc_seq_ls_acc(struct fc_seq *req_sp)
}
}
/*
* Reject sequence with ELS LS_RJT.
/**
* fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT
* @req_sp: The request sequence
* @reason: The reason the sequence is being rejected
* @explan: The explaination for the rejection
*
* If this fails due to allocation or transmit congestion, assume the
* originator will repeat the sequence.
*/
......@@ -1466,6 +1606,10 @@ static void fc_seq_ls_rjt(struct fc_seq *req_sp, enum fc_els_rjt_reason reason,
}
}
/**
* fc_exch_reset() - Reset an exchange
* @ep: The exchange to be reset
*/
static void fc_exch_reset(struct fc_exch *ep)
{
struct fc_seq *sp;
......@@ -1500,16 +1644,16 @@ static void fc_exch_reset(struct fc_exch *ep)
}
/**
* fc_exch_pool_reset() - Resets an per cpu exches pool.
* @lport: ptr to the local port
* @pool: ptr to the per cpu exches pool
* @sid: source FC ID
* @did: destination FC ID
* fc_exch_pool_reset() - Reset a per cpu exchange pool
* @lport: The local port that the exchange pool is on
* @pool: The exchange pool to be reset
* @sid: The source ID
* @did: The destination ID
*
* Resets an per cpu exches pool, 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.
* Resets a per cpu exches pool, releasing all of its sequences
* and exchanges. If sid is non-zero then reset only exchanges
* we sourced from the local port's FID. If did is non-zero then
* only reset exchanges destined for the local port's FID.
*/
static void fc_exch_pool_reset(struct fc_lport *lport,
struct fc_exch_pool *pool,
......@@ -1543,15 +1687,15 @@ static void fc_exch_pool_reset(struct fc_lport *lport,
}
/**
* fc_exch_mgr_reset() - Resets all EMs of a lport
* @lport: ptr to the local port
* @sid: source FC ID
* @did: destination FC ID
* fc_exch_mgr_reset() - Reset all EMs of a local port
* @lport: The local port whose EMs are to be reset
* @sid: The source ID
* @did: The destination ID
*
* 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.
* Reset all EMs associated with a given local port. Release all
* sequences and exchanges. If sid is non-zero then reset only the
* exchanges sent from the local port's FID. If did is non-zero then
* reset only exchanges destined for the local port's FID.
*/
void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did)
{
......@@ -1567,8 +1711,11 @@ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did)
}
EXPORT_SYMBOL(fc_exch_mgr_reset);
/*
* Handle incoming ELS REC - Read Exchange Concise.
/**
* fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests
* @sp: The sequence the REC is on
* @rfp: The REC frame
*
* Note that the requesting port may be different than the S_ID in the request.
*/
static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
......@@ -1650,10 +1797,11 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
fc_frame_free(rfp);
}
/*
* Handle response from RRQ.
* Not much to do here, really.
* Should report errors.
/**
* fc_exch_rrq_resp() - Handler for RRQ responses
* @sp: The sequence that the RRQ is on
* @fp: The RRQ frame
* @arg: The exchange that the RRQ is on
*
* TODO: fix error handler.
*/
......@@ -1695,11 +1843,25 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
/**
* This function is for exch_seq_send function pointer in
* struct libfc_function_template, see comment block on
* exch_seq_send for description of this function.
*/
static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
* fc_exch_seq_send() - Send a frame using a new exchange and sequence
* @lport: The local port to send the frame on
* @fp: The frame to be sent
* @resp: The response handler for this request
* @destructor: The destructor for the exchange
* @arg: The argument to be passed to the response handler
* @timer_msec: The timeout period for the exchange
*
* The frame pointer with some of the header's fields must be
* filled before calling this routine, those fields are:
*
* - routing control
* - FC port did
* - FC port sid
* - FC header type
* - frame control
* - parameter or relative offset
*/
static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
struct fc_frame *fp,
void (*resp)(struct fc_seq *,
struct fc_frame *fp,
......@@ -1713,7 +1875,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
struct fc_frame_header *fh;
int rc = 1;
ep = fc_exch_alloc(lp, fp);
ep = fc_exch_alloc(lport, fp);
if (!ep) {
fc_frame_free(fp);
return NULL;
......@@ -1725,7 +1887,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
ep->destructor = destructor;
ep->arg = arg;
ep->r_a_tov = FC_DEF_R_A_TOV;
ep->lp = lp;
ep->lp = lport;
sp = &ep->seq;
ep->fh_type = fh->fh_type; /* save for possbile timeout handling */
......@@ -1733,10 +1895,10 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
fc_exch_setup_hdr(ep, fp, ep->f_ctl);
sp->cnt++;
if (ep->xid <= lp->lro_xid)
if (ep->xid <= lport->lro_xid)
fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
if (unlikely(lp->tt.frame_send(lp, fp)))
if (unlikely(lport->tt.frame_send(lport, fp)))
goto err;
if (timer_msec)
......@@ -1755,21 +1917,23 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
return NULL;
}
/*
* Send ELS RRQ - Reinstate Recovery Qualifier.
/**
* fc_exch_rrq() - Send an ELS RRQ (Reinstate Recovery Qualifier) command
* @ep: The exchange to send the RRQ on
*
* This tells the remote port to stop blocking the use of
* the exchange and the seq_cnt range.
*/
static void fc_exch_rrq(struct fc_exch *ep)
{
struct fc_lport *lp;
struct fc_lport *lport;
struct fc_els_rrq *rrq;
struct fc_frame *fp;
u32 did;
lp = ep->lp;
lport = ep->lp;
fp = fc_frame_alloc(lp, sizeof(*rrq));
fp = fc_frame_alloc(lport, sizeof(*rrq));
if (!fp)
goto retry;
......@@ -1785,10 +1949,11 @@ static void fc_exch_rrq(struct fc_exch *ep)
did = ep->sid;
fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did,
fc_host_port_id(lp->host), FC_TYPE_ELS,
fc_host_port_id(lport->host), FC_TYPE_ELS,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
if (fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, lp->e_d_tov))
if (fc_exch_seq_send(lport, fp, fc_exch_rrq_resp, NULL, ep,
lport->e_d_tov))
return;
retry:
......@@ -1805,8 +1970,10 @@ static void fc_exch_rrq(struct fc_exch *ep)
}
/*
* Handle incoming ELS RRQ - Reset Recovery Qualifier.
/**
* fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests
* @sp: The sequence that the RRQ is on
* @fp: The RRQ frame
*/
static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp)
{
......@@ -1872,6 +2039,12 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp)
fc_exch_release(ep); /* drop hold from fc_exch_find */
}
/**
* fc_exch_mgr_add() - Add an exchange manager to a local port's list of EMs
* @lport: The local port to add the exchange manager to
* @mp: The exchange manager to be added to the local port
* @match: The match routine that indicates when this EM should be used
*/
struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
struct fc_exch_mgr *mp,
bool (*match)(struct fc_frame *))
......@@ -1891,6 +2064,10 @@ struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
}
EXPORT_SYMBOL(fc_exch_mgr_add);
/**
* fc_exch_mgr_destroy() - Destroy an exchange manager
* @kref: The reference to the EM to be destroyed
*/
static void fc_exch_mgr_destroy(struct kref *kref)
{
struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref);
......@@ -1900,6 +2077,10 @@ static void fc_exch_mgr_destroy(struct kref *kref)
kfree(mp);
}
/**
* fc_exch_mgr_del() - Delete an EM from a local port's list
* @ema: The exchange manager anchor identifying the EM to be deleted
*/
void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema)
{
/* remove EM anchor from EM anchors list */
......@@ -1910,9 +2091,9 @@ void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema)
EXPORT_SYMBOL(fc_exch_mgr_del);
/**
* fc_exch_mgr_list_clone() - share all exchange manager objects
* @src: source lport to clone exchange managers from
* @dst: new lport that takes references to all the exchange managers
* fc_exch_mgr_list_clone() - Share all exchange manager objects
* @src: Source lport to clone exchange managers from
* @dst: New lport that takes references to all the exchange managers
*/
int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst)
{
......@@ -1929,7 +2110,15 @@ int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst)
return -ENOMEM;
}
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
/**
* fc_exch_mgr_alloc() - Allocate an exchange manager
* @lport: The local port that the new EM will be associated with
* @class: The default FC class for new exchanges
* @min_xid: The minimum XID for exchanges from the new EM
* @max_xid: The maximum XID for exchanges from the new EM
* @match: The match routine for the new EM
*/
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
enum fc_class class,
u16 min_xid, u16 max_xid,
bool (*match)(struct fc_frame *))
......@@ -1942,7 +2131,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN ||
(min_xid & fc_cpu_mask) != 0) {
FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n",
FC_LPORT_DBG(lport, "Invalid min_xid 0x:%x and max_xid 0x:%x\n",
min_xid, max_xid);
return NULL;
}
......@@ -1985,7 +2174,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
}
kref_init(&mp->kref);
if (!fc_exch_mgr_add(lp, mp, match)) {
if (!fc_exch_mgr_add(lport, mp, match)) {
free_percpu(mp->pool);
goto free_mempool;
}
......@@ -2006,6 +2195,10 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
}
EXPORT_SYMBOL(fc_exch_mgr_alloc);
/**
* fc_exch_mgr_free() - Free all exchange managers on a local port
* @lport: The local port whose EMs are to be freed
*/
void fc_exch_mgr_free(struct fc_lport *lport)
{
struct fc_exch_mgr_anchor *ema, *next;
......@@ -2015,10 +2208,12 @@ void fc_exch_mgr_free(struct fc_lport *lport)
}
EXPORT_SYMBOL(fc_exch_mgr_free);
/*
* Receive a frame
/**
* fc_exch_recv() - Handler for received frames
* @lport: The local port the frame was received on
* @fp: The received frame
*/
void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
{
struct fc_frame_header *fh = fc_frame_header_get(fp);
struct fc_exch_mgr_anchor *ema;
......@@ -2026,8 +2221,8 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
u16 oxid;
/* lport lock ? */
if (!lp || lp->state == LPORT_ST_DISABLED) {
FC_LPORT_DBG(lp, "Receiving frames for an lport that "
if (!lport || lport->state == LPORT_ST_DISABLED) {
FC_LPORT_DBG(lport, "Receiving frames for an lport that "
"has not been initialized correctly\n");
fc_frame_free(fp);
return;
......@@ -2036,7 +2231,7 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
f_ctl = ntoh24(fh->fh_f_ctl);
oxid = ntohs(fh->fh_ox_id);
if (f_ctl & FC_FC_EX_CTX) {
list_for_each_entry(ema, &lp->ema_list, ema_list) {
list_for_each_entry(ema, &lport->ema_list, ema_list) {
if ((oxid >= ema->mp->min_xid) &&
(oxid <= ema->mp->max_xid)) {
found = 1;
......@@ -2045,13 +2240,13 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
}
if (!found) {
FC_LPORT_DBG(lp, "Received response for out "
FC_LPORT_DBG(lport, "Received response for out "
"of range oxid:%hx\n", oxid);
fc_frame_free(fp);
return;
}
} else
ema = list_entry(lp->ema_list.prev, typeof(*ema), ema_list);
ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list);
/*
* If frame is marked invalid, just drop it.
......@@ -2070,37 +2265,42 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_frame *fp)
else if (f_ctl & FC_FC_SEQ_CTX)
fc_exch_recv_resp(ema->mp, fp);
else
fc_exch_recv_req(lp, ema->mp, fp);
fc_exch_recv_req(lport, ema->mp, fp);
break;
default:
FC_LPORT_DBG(lp, "dropping invalid frame (eof %x)", fr_eof(fp));
FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)",
fr_eof(fp));
fc_frame_free(fp);
}
}
EXPORT_SYMBOL(fc_exch_recv);
int fc_exch_init(struct fc_lport *lp)
/**
* fc_exch_init() - Initialize the exchange layer for a local port
* @lport: The local port to initialize the exchange layer for
*/
int fc_exch_init(struct fc_lport *lport)
{
if (!lp->tt.seq_start_next)
lp->tt.seq_start_next = fc_seq_start_next;
if (!lport->tt.seq_start_next)
lport->tt.seq_start_next = fc_seq_start_next;
if (!lp->tt.exch_seq_send)
lp->tt.exch_seq_send = fc_exch_seq_send;
if (!lport->tt.exch_seq_send)
lport->tt.exch_seq_send = fc_exch_seq_send;
if (!lp->tt.seq_send)
lp->tt.seq_send = fc_seq_send;
if (!lport->tt.seq_send)
lport->tt.seq_send = fc_seq_send;
if (!lp->tt.seq_els_rsp_send)
lp->tt.seq_els_rsp_send = fc_seq_els_rsp_send;
if (!lport->tt.seq_els_rsp_send)
lport->tt.seq_els_rsp_send = fc_seq_els_rsp_send;
if (!lp->tt.exch_done)
lp->tt.exch_done = fc_exch_done;
if (!lport->tt.exch_done)
lport->tt.exch_done = fc_exch_done;
if (!lp->tt.exch_mgr_reset)
lp->tt.exch_mgr_reset = fc_exch_mgr_reset;
if (!lport->tt.exch_mgr_reset)
lport->tt.exch_mgr_reset = fc_exch_mgr_reset;
if (!lp->tt.seq_exch_abort)
lp->tt.seq_exch_abort = fc_seq_exch_abort;
if (!lport->tt.seq_exch_abort)
lport->tt.seq_exch_abort = fc_seq_exch_abort;
return 0;
}
......@@ -2141,7 +2341,10 @@ int fc_setup_exch_mgr()
return 0;
}
void fc_destroy_exch_mgr(void)
/**
* fc_destroy_exch_mgr() - Destroy an exchange manager
*/
void fc_destroy_exch_mgr()
{
kmem_cache_destroy(fc_em_cachep);
}
......@@ -67,6 +67,12 @@ struct kmem_cache *scsi_pkt_cachep;
#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status)
#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual)
/**
* struct fc_fcp_internal - FCP layer internal data
* @scsi_pkt_pool: Memory pool to draw FCP packets from
* @scsi_pkt_queue: Current FCP packets
* @throttled: The FCP packet queue is throttled
*/
struct fc_fcp_internal {
mempool_t *scsi_pkt_pool;
struct list_head scsi_pkt_queue;
......@@ -84,9 +90,9 @@ static void fc_fcp_recv(struct fc_seq *, struct fc_frame *, void *);
static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *);
static void fc_fcp_complete_locked(struct fc_fcp_pkt *);
static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *);
static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp);
static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *);
static void fc_timeout_error(struct fc_fcp_pkt *);
static void fc_fcp_timeout(unsigned long data);
static void fc_fcp_timeout(unsigned long);
static void fc_fcp_rec(struct fc_fcp_pkt *);
static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *);
static void fc_fcp_rec_resp(struct fc_seq *, struct fc_frame *, void *);
......@@ -125,23 +131,22 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
#define FC_FCP_DFLT_QUEUE_DEPTH 32
/**
* fc_fcp_pkt_alloc - allocation routine for scsi_pkt packet
* @lp: fc lport struct
* @gfp: gfp flags for allocation
* fc_fcp_pkt_alloc() - Allocate a fcp_pkt
* @lport: The local port that the FCP packet is for
* @gfp: GFP flags for allocation
*
* This is used by upper layer scsi driver.
* Return Value : scsi_pkt structure or null on allocation failure.
* Context : call from process context. no locking required.
* Return value: fcp_pkt structure or null on allocation failure.
* Context: Can be called from process context, no lock is required.
*/
static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp)
static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lp);
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
struct fc_fcp_pkt *fsp;
fsp = mempool_alloc(si->scsi_pkt_pool, gfp);
if (fsp) {
memset(fsp, 0, sizeof(*fsp));
fsp->lp = lp;
fsp->lp = lport;
atomic_set(&fsp->ref_cnt, 1);
init_timer(&fsp->timer);
INIT_LIST_HEAD(&fsp->list);
......@@ -151,12 +156,11 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp)
}
/**
* fc_fcp_pkt_release() - release hold on scsi_pkt packet
* @fsp: fcp packet struct
* fc_fcp_pkt_release() - Release hold on a fcp_pkt
* @fsp: The FCP packet to be released
*
* This is used by upper layer scsi driver.
* Context : call from process and interrupt context.
* no locking required
* Context: Can be called from process or interrupt context,
* no lock is required.
*/
static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp)
{
......@@ -167,20 +171,25 @@ static void fc_fcp_pkt_release(struct fc_fcp_pkt *fsp)
}
}
/**
* fc_fcp_pkt_hold() - Hold a fcp_pkt
* @fsp: The FCP packet to be held
*/
static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp)
{
atomic_inc(&fsp->ref_cnt);
}
/**
* fc_fcp_pkt_destory() - release hold on scsi_pkt packet
* @seq: exchange sequence
* @fsp: fcp packet struct
* fc_fcp_pkt_destory() - Release hold on a fcp_pkt
* @seq: The sequence that the FCP packet is on (required by destructor API)
* @fsp: The FCP packet to be released
*
* This routine is called by a destructor callback in the exch_seq_send()
* routine of the libfc Transport Template. The 'struct fc_seq' is a required
* argument even though it is not used by this routine.
*
* Release hold on scsi_pkt packet set to keep scsi_pkt
* till EM layer exch resource is not freed.
* Context : called from from EM layer.
* no locking required
* Context: No locking required.
*/
static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp)
{
......@@ -188,10 +197,10 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp)
}
/**
* fc_fcp_lock_pkt() - lock a packet and get a ref to it.
* @fsp: fcp packet
* fc_fcp_lock_pkt() - Lock a fcp_pkt and increase its reference count
* @fsp: The FCP packet to be locked and incremented
*
* We should only return error if we return a command to scsi-ml before
* We should only return error if we return a command to SCSI-ml before
* getting a response. This can happen in cases where we send a abort, but
* do not wait for the response and the abort and command can be passing
* each other on the wire/network-layer.
......@@ -216,18 +225,33 @@ static inline int fc_fcp_lock_pkt(struct fc_fcp_pkt *fsp)
return 0;
}
/**
* fc_fcp_unlock_pkt() - Release a fcp_pkt's lock and decrement its
* reference count
* @fsp: The FCP packet to be unlocked and decremented
*/
static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp)
{
spin_unlock_bh(&fsp->scsi_pkt_lock);
fc_fcp_pkt_release(fsp);
}
/**
* fc_fcp_timer_set() - Start a timer for a fcp_pkt
* @fsp: The FCP packet to start a timer for
* @delay: The timeout period for the timer
*/
static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
{
if (!(fsp->state & FC_SRB_COMPL))
mod_timer(&fsp->timer, jiffies + delay);
}
/**
* fc_fcp_send_abort() - Send an abort for exchanges associated with a
* fcp_pkt
* @fsp: The FCP packet to abort exchanges on
*/
static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
{
if (!fsp->seq_ptr)
......@@ -237,9 +261,14 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
}
/*
* Retry command.
* An abort isn't needed.
/**
* fc_fcp_retry_cmd() - Retry a fcp_pkt
* @fsp: The FCP packet to be retried
*
* Sets the status code to be FC_ERROR and then calls
* fc_fcp_complete_locked() which in turn calls fc_io_compl().
* fc_io_compl() will notify the SCSI-ml that the I/O is done.
* The SCSI-ml will retry the command.
*/
static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
{
......@@ -254,43 +283,35 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
fc_fcp_complete_locked(fsp);
}
/*
* fc_fcp_ddp_setup - calls to LLD's ddp_setup to set up DDP
* transfer for a read I/O indicated by the fc_fcp_pkt.
* @fsp: ptr to the fc_fcp_pkt
*
* This is called in exch_seq_send() when we have a newly allocated
* exchange with a valid exchange id to setup ddp.
*
* returns: none
/**
* fc_fcp_ddp_setup() - Calls a LLD's ddp_setup routine to set up DDP context
* @fsp: The FCP packet that will manage the DDP frames
* @xid: The XID that will be used for the DDP exchange
*/
void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid)
{
struct fc_lport *lp;
struct fc_lport *lport;
if (!fsp)
return;
lp = fsp->lp;
lport = fsp->lp;
if ((fsp->req_flags & FC_SRB_READ) &&
(lp->lro_enabled) && (lp->tt.ddp_setup)) {
if (lp->tt.ddp_setup(lp, xid, scsi_sglist(fsp->cmd),
(lport->lro_enabled) && (lport->tt.ddp_setup)) {
if (lport->tt.ddp_setup(lport, xid, scsi_sglist(fsp->cmd),
scsi_sg_count(fsp->cmd)))
fsp->xfer_ddp = xid;
}
}
/*
* fc_fcp_ddp_done - calls to LLD's ddp_done to release any
* DDP related resources for this I/O if it is initialized
* as a ddp transfer
* @fsp: ptr to the fc_fcp_pkt
*
* returns: none
/**
* fc_fcp_ddp_done() - Calls a LLD's ddp_done routine to release any
* DDP related resources for a fcp_pkt
* @fsp: The FCP packet that DDP had been used on
*/
static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
{
struct fc_lport *lp;
struct fc_lport *lport;
if (!fsp)
return;
......@@ -298,22 +319,22 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
if (fsp->xfer_ddp == FC_XID_UNKNOWN)
return;
lp = fsp->lp;
if (lp->tt.ddp_done) {
fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp);
lport = fsp->lp;
if (lport->tt.ddp_done) {
fsp->xfer_len = lport->tt.ddp_done(lport, fsp->xfer_ddp);
fsp->xfer_ddp = FC_XID_UNKNOWN;
}
}
/*
* Receive SCSI data from target.
* Called after receiving solicited data.
/**
* fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target
* @fsp: The FCP packet the data is on
* @fp: The data frame
*/
static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
struct scsi_cmnd *sc = fsp->cmd;
struct fc_lport *lp = fsp->lp;
struct fc_lport *lport = fsp->lp;
struct fcoe_dev_stats *stats;
struct fc_frame_header *fh;
size_t start_offset;
......@@ -363,13 +384,13 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
if (~crc != le32_to_cpu(fr_crc(fp))) {
crc_err:
stats = fc_lport_get_stats(lp);
stats = fc_lport_get_stats(lport);
stats->ErrorFrames++;
/* FIXME - per cpu count, not total count! */
if (stats->InvalidCRCCount++ < 5)
printk(KERN_WARNING "libfc: CRC error on data "
"frame for port (%6x)\n",
fc_host_port_id(lp->host));
fc_host_port_id(lport->host));
/*
* Assume the frame is total garbage.
* We may have copied it over the good part
......@@ -397,18 +418,17 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
}
/**
* fc_fcp_send_data() - Send SCSI data to target.
* @fsp: ptr to fc_fcp_pkt
* @sp: ptr to this sequence
* @offset: starting offset for this data request
* @seq_blen: the burst length for this data request
* fc_fcp_send_data() - Send SCSI data to a target
* @fsp: The FCP packet the data is on
* @sp: The sequence the data is to be sent on
* @offset: The starting offset for this data request
* @seq_blen: The burst length for this data request
*
* Called after receiving a Transfer Ready data descriptor.
* if LLD is capable of seq offload then send down seq_blen
* size of data in single frame, otherwise send multiple FC
* frames of max FC frame payload supported by target port.
*
* Returns : 0 for success.
* If the LLD is capable of sequence offload then send down the
* seq_blen ammount of data in single frame, otherwise send
* multiple frames of the maximum frame payload supported by
* the target port.
*/
static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
size_t offset, size_t seq_blen)
......@@ -417,7 +437,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
struct scsi_cmnd *sc;
struct scatterlist *sg;
struct fc_frame *fp = NULL;
struct fc_lport *lp = fsp->lp;
struct fc_lport *lport = fsp->lp;
size_t remaining;
size_t t_blen;
size_t tlen;
......@@ -426,7 +446,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
int error;
void *data = NULL;
void *page_addr;
int using_sg = lp->sg_supp;
int using_sg = lport->sg_supp;
u32 f_ctl;
WARN_ON(seq_blen <= 0);
......@@ -448,10 +468,10 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
* to max FC frame payload previously set in fsp->max_payload.
*/
t_blen = fsp->max_payload;
if (lp->seq_offload) {
t_blen = min(seq_blen, (size_t)lp->lso_max);
if (lport->seq_offload) {
t_blen = min(seq_blen, (size_t)lport->lso_max);
FC_FCP_DBG(fsp, "fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n",
fsp, seq_blen, lp->lso_max, t_blen);
fsp, seq_blen, lport->lso_max, t_blen);
}
WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD);
......@@ -463,7 +483,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
remaining = seq_blen;
fh_parm_offset = frame_offset = offset;
tlen = 0;
seq = lp->tt.seq_start_next(seq);
seq = lport->tt.seq_start_next(seq);
f_ctl = FC_FC_REL_OFF;
WARN_ON(!seq);
......@@ -486,11 +506,11 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
if (tlen % 4)
using_sg = 0;
if (using_sg) {
fp = _fc_frame_alloc(lp, 0);
fp = _fc_frame_alloc(lport, 0);
if (!fp)
return -ENOMEM;
} else {
fp = fc_frame_alloc(lp, tlen);
fp = fc_frame_alloc(lport, tlen);
if (!fp)
return -ENOMEM;
......@@ -550,7 +570,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
/*
* send fragment using for a sequence.
*/
error = lp->tt.seq_send(lp, seq, fp);
error = lport->tt.seq_send(lport, seq, fp);
if (error) {
WARN_ON(1); /* send error should be rare */
fc_fcp_retry_cmd(fsp);
......@@ -562,6 +582,11 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
return 0;
}
/**
* fc_fcp_abts_resp() - Send an ABTS response
* @fsp: The FCP packet that is being aborted
* @fp: The response frame
*/
static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
int ba_done = 1;
......@@ -598,8 +623,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
}
/**
* fc_fcp_reduce_can_queue() - drop can_queue
* @lp: lport to drop queueing for
* fc_fcp_reduce_can_queue() - Reduce the can_queue value for a local port
* @lport: The local port to reduce can_queue on
*
* If we are getting memory allocation failures, then we may
* be trying to execute too many commands. We let the running
......@@ -607,37 +632,36 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
* can_queue. Eventually we will hit the point where we run
* on all reserved structs.
*/
static void fc_fcp_reduce_can_queue(struct fc_lport *lp)
static void fc_fcp_reduce_can_queue(struct fc_lport *lport)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lp);
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
unsigned long flags;
int can_queue;
spin_lock_irqsave(lp->host->host_lock, flags);
spin_lock_irqsave(lport->host->host_lock, flags);
if (si->throttled)
goto done;
si->throttled = 1;
can_queue = lp->host->can_queue;
can_queue = lport->host->can_queue;
can_queue >>= 1;
if (!can_queue)
can_queue = 1;
lp->host->can_queue = can_queue;
shost_printk(KERN_ERR, lp->host, "libfc: Could not allocate frame.\n"
lport->host->can_queue = can_queue;
shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
"Reducing can_queue to %d.\n", can_queue);
done:
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
}
/**
* fc_fcp_recv() - Reveive FCP frames
* fc_fcp_recv() - Reveive an FCP frame
* @seq: The sequence the frame is on
* @fp: The FC frame
* @fp: The received frame
* @arg: The related FCP packet
*
* Return : None
* Context : called from Soft IRQ context
* can not called holding list lock
* Context: Called from Soft IRQ context. Can not be called
* holding the FCP packet list lock.
*/
static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
......@@ -710,6 +734,11 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fc_fcp_reduce_can_queue(lport);
}
/**
* fc_fcp_resp() - Handler for FCP responses
* @fsp: The FCP packet the response is for
* @fp: The response frame
*/
static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
struct fc_frame_header *fh;
......@@ -823,15 +852,16 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
}
/**
* fc_fcp_complete_locked() - complete processing of a fcp packet
* @fsp: fcp packet
* fc_fcp_complete_locked() - Complete processing of a fcp_pkt with the
* fcp_pkt lock held
* @fsp: The FCP packet to be completed
*
* This function may sleep if a timer is pending. The packet lock must be
* held, and the host lock must not be held.
*/
static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
{
struct fc_lport *lp = fsp->lp;
struct fc_lport *lport = fsp->lp;
struct fc_seq *seq;
struct fc_exch *ep;
u32 f_ctl;
......@@ -862,7 +892,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
struct fc_frame *conf_frame;
struct fc_seq *csp;
csp = lp->tt.seq_start_next(seq);
csp = lport->tt.seq_start_next(seq);
conf_frame = fc_frame_alloc(fsp->lp, 0);
if (conf_frame) {
f_ctl = FC_FC_SEQ_INIT;
......@@ -871,43 +901,48 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
fc_fill_fc_hdr(conf_frame, FC_RCTL_DD_SOL_CTL,
ep->did, ep->sid,
FC_TYPE_FCP, f_ctl, 0);
lp->tt.seq_send(lp, csp, conf_frame);
lport->tt.seq_send(lport, csp, conf_frame);
}
}
lp->tt.exch_done(seq);
lport->tt.exch_done(seq);
}
fc_io_compl(fsp);
}
/**
* fc_fcp_cleanup_cmd() - Cancel the active exchange on a fcp_pkt
* @fsp: The FCP packet whose exchanges should be canceled
* @error: The reason for the cancellation
*/
static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error)
{
struct fc_lport *lp = fsp->lp;
struct fc_lport *lport = fsp->lp;
if (fsp->seq_ptr) {
lp->tt.exch_done(fsp->seq_ptr);
lport->tt.exch_done(fsp->seq_ptr);
fsp->seq_ptr = NULL;
}
fsp->status_code = error;
}
/**
* fc_fcp_cleanup_each_cmd() - Cleanup active commads
* @lp: logical port
* @id: target id
* @lun: lun
* @error: fsp status code
* fc_fcp_cleanup_each_cmd() - Cancel all exchanges on a local port
* @lport: The local port whose exchanges should be canceled
* @id: The target's ID
* @lun: The LUN
* @error: The reason for cancellation
*
* If lun or id is -1, they are ignored.
*/
static void fc_fcp_cleanup_each_cmd(struct fc_lport *lp, unsigned int id,
static void fc_fcp_cleanup_each_cmd(struct fc_lport *lport, unsigned int id,
unsigned int lun, int error)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lp);
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
struct fc_fcp_pkt *fsp;
struct scsi_cmnd *sc_cmd;
unsigned long flags;
spin_lock_irqsave(lp->host->host_lock, flags);
spin_lock_irqsave(lport->host->host_lock, flags);
restart:
list_for_each_entry(fsp, &si->scsi_pkt_queue, list) {
sc_cmd = fsp->cmd;
......@@ -918,7 +953,7 @@ static void fc_fcp_cleanup_each_cmd(struct fc_lport *lp, unsigned int id,
continue;
fc_fcp_pkt_hold(fsp);
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
if (!fc_fcp_lock_pkt(fsp)) {
fc_fcp_cleanup_cmd(fsp, error);
......@@ -927,35 +962,36 @@ static void fc_fcp_cleanup_each_cmd(struct fc_lport *lp, unsigned int id,
}
fc_fcp_pkt_release(fsp);
spin_lock_irqsave(lp->host->host_lock, flags);
spin_lock_irqsave(lport->host->host_lock, flags);
/*
* while we dropped the lock multiple pkts could
* have been released, so we have to start over.
*/
goto restart;
}
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
}
static void fc_fcp_abort_io(struct fc_lport *lp)
/**
* fc_fcp_abort_io() - Abort all FCP-SCSI exchanges on a local port
* @lport: The local port whose exchanges are to be aborted
*/
static void fc_fcp_abort_io(struct fc_lport *lport)
{
fc_fcp_cleanup_each_cmd(lp, -1, -1, FC_HRD_ERROR);
fc_fcp_cleanup_each_cmd(lport, -1, -1, FC_HRD_ERROR);
}
/**
* fc_fcp_pkt_send() - send a fcp packet to the lower level.
* @lp: fc lport
* @fsp: fc packet.
* fc_fcp_pkt_send() - Send a fcp_pkt
* @lport: The local port to send the FCP packet on
* @fsp: The FCP packet to send
*
* This is called by upper layer protocol.
* Return : zero for success and -1 for failure
* Context : called from queuecommand which can be called from process
* or scsi soft irq.
* Locks : called with the host lock and irqs disabled.
* Return: Zero for success and -1 for failure
* Locks: Called with the host lock and irqs disabled.
*/
static int fc_fcp_pkt_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp)
static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lp);
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
int rc;
fsp->cmd->SCp.ptr = (char *)fsp;
......@@ -967,16 +1003,22 @@ static int fc_fcp_pkt_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp)
memcpy(fsp->cdb_cmd.fc_cdb, fsp->cmd->cmnd, fsp->cmd->cmd_len);
list_add_tail(&fsp->list, &si->scsi_pkt_queue);
spin_unlock_irq(lp->host->host_lock);
rc = lp->tt.fcp_cmd_send(lp, fsp, fc_fcp_recv);
spin_lock_irq(lp->host->host_lock);
spin_unlock_irq(lport->host->host_lock);
rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv);
spin_lock_irq(lport->host->host_lock);
if (rc)
list_del(&fsp->list);
return rc;
}
static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
/**
* fc_fcp_cmd_send() - Send a FCP command
* @lport: The local port to send the command on
* @fsp: The FCP packet the command is on
* @resp: The handler for the response
*/
static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
void (*resp)(struct fc_seq *,
struct fc_frame *fp,
void *arg))
......@@ -984,14 +1026,14 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
struct fc_frame *fp;
struct fc_seq *seq;
struct fc_rport *rport;
struct fc_rport_libfc_priv *rp;
struct fc_rport_libfc_priv *rpriv;
const size_t len = sizeof(fsp->cdb_cmd);
int rc = 0;
if (fc_fcp_lock_pkt(fsp))
return 0;
fp = fc_frame_alloc(lp, sizeof(fsp->cdb_cmd));
fp = fc_frame_alloc(lport, sizeof(fsp->cdb_cmd));
if (!fp) {
rc = -1;
goto unlock;
......@@ -1001,13 +1043,14 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
fr_fsp(fp) = fsp;
rport = fsp->rport;
fsp->max_payload = rport->maxframe_size;
rp = rport->dd_data;
rpriv = rport->dd_data;
fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id,
fc_host_port_id(rp->local_port->host), FC_TYPE_FCP,
fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
seq = lp->tt.exch_seq_send(lp, fp, resp, fc_fcp_pkt_destroy, fsp, 0);
seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy,
fsp, 0);
if (!seq) {
rc = -1;
goto unlock;
......@@ -1025,8 +1068,10 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
return rc;
}
/*
* transport error handler
/**
* fc_fcp_error() - Handler for FCP layer errors
* @fsp: The FCP packet the error is on
* @fp: The frame that has errored
*/
static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
......@@ -1051,9 +1096,11 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
fc_fcp_unlock_pkt(fsp);
}
/*
* Scsi abort handler- calls to send an abort
* and then wait for abort completion
/**
* fc_fcp_pkt_abort() - Abort a fcp_pkt
* @fsp: The FCP packet to abort on
*
* Called to send an abort and then wait for abort completion
*/
static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
{
......@@ -1082,14 +1129,15 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
return rc;
}
/*
* Retry LUN reset after resource allocation failed.
/**
* fc_lun_reset_send() - Send LUN reset command
* @data: The FCP packet that identifies the LUN to be reset
*/
static void fc_lun_reset_send(unsigned long data)
{
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
struct fc_lport *lp = fsp->lp;
if (lp->tt.fcp_cmd_send(lp, fsp, fc_tm_done)) {
struct fc_lport *lport = fsp->lp;
if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) {
if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY)
return;
if (fc_fcp_lock_pkt(fsp))
......@@ -1100,11 +1148,15 @@ static void fc_lun_reset_send(unsigned long data)
}
}
/*
* Scsi device reset handler- send a LUN RESET to the device
* and wait for reset reply
*/
static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
/**
* fc_lun_reset() - Send a LUN RESET command to a device
* and wait for the reply
* @lport: The local port to sent the comand on
* @fsp: The FCP packet that identifies the LUN to be reset
* @id: The SCSI command ID
* @lun: The LUN ID to be reset
*/
static int fc_lun_reset(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
unsigned int id, unsigned int lun)
{
int rc;
......@@ -1132,14 +1184,14 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
spin_lock_bh(&fsp->scsi_pkt_lock);
if (fsp->seq_ptr) {
lp->tt.exch_done(fsp->seq_ptr);
lport->tt.exch_done(fsp->seq_ptr);
fsp->seq_ptr = NULL;
}
fsp->wait_for_comp = 0;
spin_unlock_bh(&fsp->scsi_pkt_lock);
if (!rc) {
FC_SCSI_DBG(lp, "lun reset failed\n");
FC_SCSI_DBG(lport, "lun reset failed\n");
return FAILED;
}
......@@ -1147,13 +1199,16 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
if (fsp->cdb_status != FCP_TMF_CMPL)
return FAILED;
FC_SCSI_DBG(lp, "lun reset to lun %u completed\n", lun);
fc_fcp_cleanup_each_cmd(lp, id, lun, FC_CMD_ABORTED);
FC_SCSI_DBG(lport, "lun reset to lun %u completed\n", lun);
fc_fcp_cleanup_each_cmd(lport, id, lun, FC_CMD_ABORTED);
return SUCCESS;
}
/*
* Task Managment response handler
/**
* fc_tm_done() - Task Managment response handler
* @seq: The sequence that the response is on
* @fp: The response frame
* @arg: The FCP packet the response is for
*/
static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
......@@ -1190,34 +1245,31 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fc_fcp_unlock_pkt(fsp);
}
static void fc_fcp_cleanup(struct fc_lport *lp)
/**
* fc_fcp_cleanup() - Cleanup all FCP exchanges on a local port
* @lport: The local port to be cleaned up
*/
static void fc_fcp_cleanup(struct fc_lport *lport)
{
fc_fcp_cleanup_each_cmd(lp, -1, -1, FC_ERROR);
fc_fcp_cleanup_each_cmd(lport, -1, -1, FC_ERROR);
}
/*
* fc_fcp_timeout: called by OS timer function.
*
* The timer has been inactivated and must be reactivated if desired
* using fc_fcp_timer_set().
*
* Algorithm:
*
* If REC is supported, just issue it, and return. The REC exchange will
* complete or time out, and recovery can continue at that point.
*
* Otherwise, if the response has been received without all the data,
* it has been ER_TIMEOUT since the response was received.
/**
* fc_fcp_timeout() - Handler for fcp_pkt timeouts
* @data: The FCP packet that has timed out
*
* If the response has not been received,
* we see if data was received recently. If it has been, we continue waiting,
* otherwise, we abort the command.
* If REC is supported then just issue it and return. The REC exchange will
* complete or time out and recovery can continue at that point. Otherwise,
* if the response has been received without all the data it has been
* ER_TIMEOUT since the response was received. If the response has not been
* received we see if data was received recently. If it has been then we
* continue waiting, otherwise, we abort the command.
*/
static void fc_fcp_timeout(unsigned long data)
{
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
struct fc_rport *rport = fsp->rport;
struct fc_rport_libfc_priv *rp = rport->dd_data;
struct fc_rport_libfc_priv *rpriv = rport->dd_data;
if (fc_fcp_lock_pkt(fsp))
return;
......@@ -1227,7 +1279,7 @@ static void fc_fcp_timeout(unsigned long data)
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
if (rp->flags & FC_RP_FLAGS_REC_SUPPORTED)
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
fc_fcp_rec(fsp);
else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2),
jiffies))
......@@ -1241,35 +1293,37 @@ static void fc_fcp_timeout(unsigned long data)
fc_fcp_unlock_pkt(fsp);
}
/*
* Send a REC ELS request
/**
* fc_fcp_rec() - Send a REC ELS request
* @fsp: The FCP packet to send the REC request on
*/
static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
{
struct fc_lport *lp;
struct fc_lport *lport;
struct fc_frame *fp;
struct fc_rport *rport;
struct fc_rport_libfc_priv *rp;
struct fc_rport_libfc_priv *rpriv;
lp = fsp->lp;
lport = fsp->lp;
rport = fsp->rport;
rp = rport->dd_data;
if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) {
rpriv = rport->dd_data;
if (!fsp->seq_ptr || rpriv->rp_state != RPORT_ST_READY) {
fsp->status_code = FC_HRD_ERROR;
fsp->io_status = 0;
fc_fcp_complete_locked(fsp);
return;
}
fp = fc_frame_alloc(lp, sizeof(struct fc_els_rec));
fp = fc_frame_alloc(lport, sizeof(struct fc_els_rec));
if (!fp)
goto retry;
fr_seq(fp) = fsp->seq_ptr;
fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id,
fc_host_port_id(rp->local_port->host), FC_TYPE_ELS,
fc_host_port_id(rpriv->local_port->host), FC_TYPE_ELS,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
if (lp->tt.elsct_send(lp, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp,
fsp, jiffies_to_msecs(FC_SCSI_REC_TOV))) {
if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC,
fc_fcp_rec_resp, fsp,
jiffies_to_msecs(FC_SCSI_REC_TOV))) {
fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */
return;
}
......@@ -1280,12 +1334,16 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
fc_timeout_error(fsp);
}
/*
* Receive handler for REC ELS frame
* if it is a reject then let the scsi layer to handle
* the timeout. if it is a LS_ACC then if the io was not completed
* then set the timeout and return otherwise complete the exchange
* and tell the scsi layer to restart the I/O.
/**
* fc_fcp_rec_resp() - Handler for REC ELS responses
* @seq: The sequence the response is on
* @fp: The response frame
* @arg: The FCP packet the response is on
*
* If the response is a reject then the scsi layer will handle
* the timeout. If the response is a LS_ACC then if the I/O was not completed
* set the timeout and return. If the I/O was completed then complete the
* exchange and tell the SCSI layer.
*/
static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
......@@ -1297,7 +1355,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
u32 offset;
enum dma_data_direction data_dir;
enum fc_rctl r_ctl;
struct fc_rport_libfc_priv *rp;
struct fc_rport_libfc_priv *rpriv;
if (IS_ERR(fp)) {
fc_fcp_rec_error(fsp, fp);
......@@ -1320,13 +1378,13 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
/* fall through */
case ELS_RJT_UNSUP:
FC_FCP_DBG(fsp, "device does not support REC\n");
rp = fsp->rport->dd_data;
rpriv = fsp->rport->dd_data;
/*
* if we do not spport RECs or got some bogus
* reason then resetup timer so we check for
* making progress.
*/
rp->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
break;
case ELS_RJT_LOGIC:
......@@ -1423,8 +1481,10 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fc_frame_free(fp);
}
/*
* Handle error response or timeout for REC exchange.
/**
* fc_fcp_rec_error() - Handler for REC errors
* @fsp: The FCP packet the error is on
* @fp: The REC frame
*/
static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
......@@ -1463,10 +1523,9 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
fc_fcp_pkt_release(fsp); /* drop hold for outstanding REC */
}
/*
* Time out error routine:
* abort's the I/O close the exchange and
* send completion notification to scsi layer
/**
* fc_timeout_error() - Handler for fcp_pkt timeouts
* @fsp: The FCP packt that has timed out
*/
static void fc_timeout_error(struct fc_fcp_pkt *fsp)
{
......@@ -1480,16 +1539,18 @@ static void fc_timeout_error(struct fc_fcp_pkt *fsp)
fc_fcp_send_abort(fsp);
}
/*
* Sequence retransmission request.
/**
* fc_fcp_srr() - Send a SRR request (Sequence Retransmission Request)
* @fsp: The FCP packet the SRR is to be sent on
* @r_ctl: The R_CTL field for the SRR request
* This is called after receiving status but insufficient data, or
* when expecting status but the request has timed out.
*/
static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
{
struct fc_lport *lp = fsp->lp;
struct fc_lport *lport = fsp->lp;
struct fc_rport *rport;
struct fc_rport_libfc_priv *rp;
struct fc_rport_libfc_priv *rpriv;
struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr);
struct fc_seq *seq;
struct fcp_srr *srr;
......@@ -1497,12 +1558,13 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
u8 cdb_op;
rport = fsp->rport;
rp = rport->dd_data;
rpriv = rport->dd_data;
cdb_op = fsp->cdb_cmd.fc_cdb[0];
if (!(rp->flags & FC_RP_FLAGS_RETRY) || rp->rp_state != RPORT_ST_READY)
if (!(rpriv->flags & FC_RP_FLAGS_RETRY) ||
rpriv->rp_state != RPORT_ST_READY)
goto retry; /* shouldn't happen */
fp = fc_frame_alloc(lp, sizeof(*srr));
fp = fc_frame_alloc(lport, sizeof(*srr));
if (!fp)
goto retry;
......@@ -1515,10 +1577,10 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
srr->srr_rel_off = htonl(offset);
fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id,
fc_host_port_id(rp->local_port->host), FC_TYPE_FCP,
fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP,
FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
seq = lp->tt.exch_seq_send(lp, fp, fc_fcp_srr_resp, NULL,
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL,
fsp, jiffies_to_msecs(FC_SCSI_REC_TOV));
if (!seq)
goto retry;
......@@ -1533,8 +1595,11 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
fc_fcp_retry_cmd(fsp);
}
/*
* Handle response from SRR.
/**
* fc_fcp_srr_resp() - Handler for SRR response
* @seq: The sequence the SRR is on
* @fp: The SRR frame
* @arg: The FCP packet the SRR is on
*/
static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
......@@ -1580,6 +1645,11 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */
}
/**
* fc_fcp_srr_error() - Handler for SRR errors
* @fsp: The FCP packet that the SRR error is on
* @fp: The SRR frame
*/
static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
if (fc_fcp_lock_pkt(fsp))
......@@ -1604,31 +1674,36 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
fc_fcp_pkt_release(fsp); /* drop hold for outstanding SRR */
}
static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp)
/**
* fc_fcp_lport_queue_ready() - Determine if the lport and it's queue is ready
* @lport: The local port to be checked
*/
static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport)
{
/* lock ? */
return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull;
return (lport->state == LPORT_ST_READY) &&
lport->link_up && !lport->qfull;
}
/**
* fc_queuecommand - The queuecommand function of the scsi template
* @cmd: struct scsi_cmnd to be executed
* @done: Callback function to be called when cmd is completed
* fc_queuecommand() - The queuecommand function of the SCSI template
* @cmd: The scsi_cmnd to be executed
* @done: The callback function to be called when the scsi_cmnd is complete
*
* this is the i/o strategy routine, called by the scsi layer
* this routine is called with holding the host_lock.
* This is the i/o strategy routine, called by the SCSI layer. This routine
* is called with the host_lock held.
*/
int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
{
struct fc_lport *lp;
struct fc_lport *lport;
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
struct fc_fcp_pkt *fsp;
struct fc_rport_libfc_priv *rp;
struct fc_rport_libfc_priv *rpriv;
int rval;
int rc = 0;
struct fcoe_dev_stats *stats;
lp = shost_priv(sc_cmd->device->host);
lport = shost_priv(sc_cmd->device->host);
rval = fc_remote_port_chkready(rport);
if (rval) {
......@@ -1647,14 +1722,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
goto out;
}
rp = rport->dd_data;
rpriv = rport->dd_data;
if (!fc_fcp_lport_queue_ready(lp)) {
if (!fc_fcp_lport_queue_ready(lport)) {
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
fsp = fc_fcp_pkt_alloc(lp, GFP_ATOMIC);
fsp = fc_fcp_pkt_alloc(lport, GFP_ATOMIC);
if (fsp == NULL) {
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
......@@ -1664,7 +1739,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
* build the libfc request pkt
*/
fsp->cmd = sc_cmd; /* save the cmd */
fsp->lp = lp; /* save the softc ptr */
fsp->lp = lport; /* save the softc ptr */
fsp->rport = rport; /* set the remote port ptr */
fsp->xfer_ddp = FC_XID_UNKNOWN;
sc_cmd->scsi_done = done;
......@@ -1678,7 +1753,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
/*
* setup the data direction
*/
stats = fc_lport_get_stats(lp);
stats = fc_lport_get_stats(lport);
if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
fsp->req_flags = FC_SRB_READ;
stats->InputRequests++;
......@@ -1692,7 +1767,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
stats->ControlRequests++;
}
fsp->tgt_flags = rp->flags;
fsp->tgt_flags = rpriv->flags;
init_timer(&fsp->timer);
fsp->timer.data = (unsigned long)fsp;
......@@ -1702,7 +1777,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
* if we get -1 return then put the request in the pending
* queue.
*/
rval = fc_fcp_pkt_send(lp, fsp);
rval = fc_fcp_pkt_send(lport, fsp);
if (rval != 0) {
fsp->state = FC_SRB_FREE;
fc_fcp_pkt_release(fsp);
......@@ -1715,17 +1790,16 @@ EXPORT_SYMBOL(fc_queuecommand);
/**
* fc_io_compl() - Handle responses for completed commands
* @fsp: scsi packet
*
* Translates a error to a Linux SCSI error.
* @fsp: The FCP packet that is complete
*
* Translates fcp_pkt errors to a Linux SCSI errors.
* The fcp packet lock must be held when calling.
*/
static void fc_io_compl(struct fc_fcp_pkt *fsp)
{
struct fc_fcp_internal *si;
struct scsi_cmnd *sc_cmd;
struct fc_lport *lp;
struct fc_lport *lport;
unsigned long flags;
/* release outstanding ddp context */
......@@ -1738,11 +1812,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
spin_lock_bh(&fsp->scsi_pkt_lock);
}
lp = fsp->lp;
si = fc_get_scsi_internal(lp);
spin_lock_irqsave(lp->host->host_lock, flags);
lport = fsp->lp;
si = fc_get_scsi_internal(lport);
spin_lock_irqsave(lport->host->host_lock, flags);
if (!fsp->cmd) {
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
return;
}
......@@ -1759,7 +1833,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
fsp->cmd = NULL;
if (!sc_cmd->SCp.ptr) {
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
return;
}
......@@ -1826,7 +1900,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
list_del(&fsp->list);
sc_cmd->SCp.ptr = NULL;
sc_cmd->scsi_done(sc_cmd);
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
/* release ref from initial allocation in queue command */
fc_fcp_pkt_release(fsp);
......@@ -1834,35 +1908,34 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
/**
* fc_eh_abort() - Abort a command
* @sc_cmd: scsi command to abort
* @sc_cmd: The SCSI command to abort
*
* From scsi host template.
* send ABTS to the target device and wait for the response
* sc_cmd is the pointer to the command to be aborted.
* From SCSI host template.
* Send an ABTS to the target device and wait for the response.
*/
int fc_eh_abort(struct scsi_cmnd *sc_cmd)
{
struct fc_fcp_pkt *fsp;
struct fc_lport *lp;
struct fc_lport *lport;
int rc = FAILED;
unsigned long flags;
lp = shost_priv(sc_cmd->device->host);
if (lp->state != LPORT_ST_READY)
lport = shost_priv(sc_cmd->device->host);
if (lport->state != LPORT_ST_READY)
return rc;
else if (!lp->link_up)
else if (!lport->link_up)
return rc;
spin_lock_irqsave(lp->host->host_lock, flags);
spin_lock_irqsave(lport->host->host_lock, flags);
fsp = CMD_SP(sc_cmd);
if (!fsp) {
/* command completed while scsi eh was setting up */
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
return SUCCESS;
}
/* grab a ref so the fsp and sc_cmd cannot be relased from under us */
fc_fcp_pkt_hold(fsp);
spin_unlock_irqrestore(lp->host->host_lock, flags);
spin_unlock_irqrestore(lport->host->host_lock, flags);
if (fc_fcp_lock_pkt(fsp)) {
/* completed while we were waiting for timer to be deleted */
......@@ -1880,34 +1953,32 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
EXPORT_SYMBOL(fc_eh_abort);
/**
* fc_eh_device_reset() Reset a single LUN
* @sc_cmd: scsi command
* fc_eh_device_reset() - Reset a single LUN
* @sc_cmd: The SCSI command which identifies the device whose
* LUN is to be reset
*
* Set from scsi host template to send tm cmd to the target and wait for the
* response.
* Set from SCSI host template.
*/
int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
{
struct fc_lport *lp;
struct fc_lport *lport;
struct fc_fcp_pkt *fsp;
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
int rc = FAILED;
struct fc_rport_libfc_priv *rp;
int rval;
rval = fc_remote_port_chkready(rport);
if (rval)
goto out;
rp = rport->dd_data;
lp = shost_priv(sc_cmd->device->host);
lport = shost_priv(sc_cmd->device->host);
if (lp->state != LPORT_ST_READY)
if (lport->state != LPORT_ST_READY)
return rc;
FC_SCSI_DBG(lp, "Resetting rport (%6x)\n", rport->port_id);
FC_SCSI_DBG(lport, "Resetting rport (%6x)\n", rport->port_id);
fsp = fc_fcp_pkt_alloc(lp, GFP_NOIO);
fsp = fc_fcp_pkt_alloc(lport, GFP_NOIO);
if (fsp == NULL) {
printk(KERN_WARNING "libfc: could not allocate scsi_pkt\n");
sc_cmd->result = DID_NO_CONNECT << 16;
......@@ -1919,13 +1990,13 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
* the sc passed in is not setup for execution like when sent
* through the queuecommand callout.
*/
fsp->lp = lp; /* save the softc ptr */
fsp->lp = lport; /* save the softc ptr */
fsp->rport = rport; /* set the remote port ptr */
/*
* flush outstanding commands
*/
rc = fc_lun_reset(lp, fsp, scmd_id(sc_cmd), sc_cmd->device->lun);
rc = fc_lun_reset(lport, fsp, scmd_id(sc_cmd), sc_cmd->device->lun);
fsp->state = FC_SRB_FREE;
fc_fcp_pkt_release(fsp);
......@@ -1935,38 +2006,39 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
EXPORT_SYMBOL(fc_eh_device_reset);
/**
* fc_eh_host_reset() - The reset function will reset the ports on the host.
* @sc_cmd: scsi command
* fc_eh_host_reset() - Reset a Scsi_Host.
* @sc_cmd: The SCSI command that identifies the SCSI host to be reset
*/
int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
{
struct Scsi_Host *shost = sc_cmd->device->host;
struct fc_lport *lp = shost_priv(shost);
struct fc_lport *lport = shost_priv(shost);
unsigned long wait_tmo;
FC_SCSI_DBG(lp, "Resetting host\n");
FC_SCSI_DBG(lport, "Resetting host\n");
lp->tt.lport_reset(lp);
lport->tt.lport_reset(lport);
wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT;
while (!fc_fcp_lport_queue_ready(lp) && time_before(jiffies, wait_tmo))
while (!fc_fcp_lport_queue_ready(lport) && time_before(jiffies,
wait_tmo))
msleep(1000);
if (fc_fcp_lport_queue_ready(lp)) {
if (fc_fcp_lport_queue_ready(lport)) {
shost_printk(KERN_INFO, shost, "libfc: Host reset succeeded "
"on port (%6x)\n", fc_host_port_id(lp->host));
"on port (%6x)\n", fc_host_port_id(lport->host));
return SUCCESS;
} else {
shost_printk(KERN_INFO, shost, "libfc: Host reset failed, "
"port (%6x) is not ready.\n",
fc_host_port_id(lp->host));
fc_host_port_id(lport->host));
return FAILED;
}
}
EXPORT_SYMBOL(fc_eh_host_reset);
/**
* fc_slave_alloc() - configure queue depth
* @sdev: scsi device
* fc_slave_alloc() - Configure the queue depth of a Scsi_Host
* @sdev: The SCSI device that identifies the SCSI host
*
* Configures queue depth based on host's cmd_per_len. If not set
* then we use the libfc default.
......@@ -1988,6 +2060,12 @@ int fc_slave_alloc(struct scsi_device *sdev)
}
EXPORT_SYMBOL(fc_slave_alloc);
/**
* fc_change_queue_depth() - Change a device's queue depth
* @sdev: The SCSI device whose queue depth is to change
* @qdepth: The new queue depth
* @reason: The resason for the change
*/
int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
{
switch (reason) {
......@@ -2007,6 +2085,11 @@ int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
}
EXPORT_SYMBOL(fc_change_queue_depth);
/**
* fc_change_queue_type() - Change a device's queue type
* @sdev: The SCSI device whose queue depth is to change
* @tag_type: Identifier for queue type
*/
int fc_change_queue_type(struct scsi_device *sdev, int tag_type)
{
if (sdev->tagged_supported) {
......@@ -2022,17 +2105,21 @@ int fc_change_queue_type(struct scsi_device *sdev, int tag_type)
}
EXPORT_SYMBOL(fc_change_queue_type);
void fc_fcp_destroy(struct fc_lport *lp)
/**
* fc_fcp_destory() - Tear down the FCP layer for a given local port
* @lport: The local port that no longer needs the FCP layer
*/
void fc_fcp_destroy(struct fc_lport *lport)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lp);
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
if (!list_empty(&si->scsi_pkt_queue))
printk(KERN_ERR "libfc: Leaked SCSI packets when destroying "
"port (%6x)\n", fc_host_port_id(lp->host));
"port (%6x)\n", fc_host_port_id(lport->host));
mempool_destroy(si->scsi_pkt_pool);
kfree(si);
lp->scsi_priv = NULL;
lport->scsi_priv = NULL;
}
EXPORT_SYMBOL(fc_fcp_destroy);
......@@ -2058,24 +2145,28 @@ void fc_destroy_fcp()
kmem_cache_destroy(scsi_pkt_cachep);
}
int fc_fcp_init(struct fc_lport *lp)
/**
* fc_fcp_init() - Initialize the FCP layer for a local port
* @lport: The local port to initialize the exchange layer for
*/
int fc_fcp_init(struct fc_lport *lport)
{
int rc;
struct fc_fcp_internal *si;
if (!lp->tt.fcp_cmd_send)
lp->tt.fcp_cmd_send = fc_fcp_cmd_send;
if (!lport->tt.fcp_cmd_send)
lport->tt.fcp_cmd_send = fc_fcp_cmd_send;
if (!lp->tt.fcp_cleanup)
lp->tt.fcp_cleanup = fc_fcp_cleanup;
if (!lport->tt.fcp_cleanup)
lport->tt.fcp_cleanup = fc_fcp_cleanup;
if (!lp->tt.fcp_abort_io)
lp->tt.fcp_abort_io = fc_fcp_abort_io;
if (!lport->tt.fcp_abort_io)
lport->tt.fcp_abort_io = fc_fcp_abort_io;
si = kzalloc(sizeof(struct fc_fcp_internal), GFP_KERNEL);
if (!si)
return -ENOMEM;
lp->scsi_priv = si;
lport->scsi_priv = si;
INIT_LIST_HEAD(&si->scsi_pkt_queue);
si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep);
......
......@@ -32,12 +32,12 @@
extern unsigned int fc_debug_logging;
#define FC_CHECK_LOGGING(LEVEL, CMD) \
do { \
do { \
if (unlikely(fc_debug_logging & LEVEL)) \
do { \
CMD; \
} while (0); \
} while (0)
} while (0)
#define FC_LIBFC_DBG(fmt, args...) \
FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \
......
......@@ -146,6 +146,11 @@ struct fc_bsg_info {
size_t offset;
};
/**
* fc_frame_drop() - Dummy frame handler
* @lport: The local port the frame was received on
* @fp: The received frame
*/
static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
{
fc_frame_free(fp);
......@@ -172,7 +177,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
switch (event) {
case RPORT_EV_READY:
if (lport->state == LPORT_ST_DNS) {
lport->dns_rp = rdata;
lport->dns_rdata = rdata;
fc_lport_enter_ns(lport, LPORT_ST_RNN_ID);
} else {
FC_LPORT_DBG(lport, "Received an READY event "
......@@ -187,7 +192,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
case RPORT_EV_LOGO:
case RPORT_EV_FAILED:
case RPORT_EV_STOP:
lport->dns_rp = NULL;
lport->dns_rdata = NULL;
break;
case RPORT_EV_NONE:
break;
......@@ -212,7 +217,7 @@ static const char *fc_lport_state(struct fc_lport *lport)
/**
* fc_lport_ptp_setup() - Create an rport for point-to-point mode
* @lport: The lport to attach the ptp rport to
* @fid: The FID of the ptp rport
* @remote_fid: The FID of the ptp rport
* @remote_wwpn: The WWPN of the ptp rport
* @remote_wwnn: The WWNN of the ptp rport
*/
......@@ -221,18 +226,22 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
u64 remote_wwnn)
{
mutex_lock(&lport->disc.disc_mutex);
if (lport->ptp_rp)
lport->tt.rport_logoff(lport->ptp_rp);
lport->ptp_rp = lport->tt.rport_create(lport, remote_fid);
lport->ptp_rp->ids.port_name = remote_wwpn;
lport->ptp_rp->ids.node_name = remote_wwnn;
if (lport->ptp_rdata)
lport->tt.rport_logoff(lport->ptp_rdata);
lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid);
lport->ptp_rdata->ids.port_name = remote_wwpn;
lport->ptp_rdata->ids.node_name = remote_wwnn;
mutex_unlock(&lport->disc.disc_mutex);
lport->tt.rport_login(lport->ptp_rp);
lport->tt.rport_login(lport->ptp_rdata);
fc_lport_enter_ready(lport);
}
/**
* fc_get_host_port_type() - Return the port type of the given Scsi_Host
* @shost: The SCSI host whose port type is to be determined
*/
void fc_get_host_port_type(struct Scsi_Host *shost)
{
/* TODO - currently just NPORT */
......@@ -240,25 +249,33 @@ void fc_get_host_port_type(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(fc_get_host_port_type);
/**
* fc_get_host_port_state() - Return the port state of the given Scsi_Host
* @shost: The SCSI host whose port state is to be determined
*/
void fc_get_host_port_state(struct Scsi_Host *shost)
{
struct fc_lport *lp = shost_priv(shost);
struct fc_lport *lport = shost_priv(shost);
mutex_lock(&lp->lp_mutex);
if (!lp->link_up)
mutex_lock(&lport->lp_mutex);
if (!lport->link_up)
fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
else
switch (lp->state) {
switch (lport->state) {
case LPORT_ST_READY:
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
break;
default:
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
}
mutex_unlock(&lp->lp_mutex);
mutex_unlock(&lport->lp_mutex);
}
EXPORT_SYMBOL(fc_get_host_port_state);
/**
* fc_get_host_speed() - Return the speed of the given Scsi_Host
* @shost: The SCSI host whose port speed is to be determined
*/
void fc_get_host_speed(struct Scsi_Host *shost)
{
struct fc_lport *lport = shost_priv(shost);
......@@ -267,24 +284,28 @@ void fc_get_host_speed(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(fc_get_host_speed);
/**
* fc_get_host_stats() - Return the Scsi_Host's statistics
* @shost: The SCSI host whose statistics are to be returned
*/
struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
{
struct fc_host_statistics *fcoe_stats;
struct fc_lport *lp = shost_priv(shost);
struct fc_lport *lport = shost_priv(shost);
struct timespec v0, v1;
unsigned int cpu;
fcoe_stats = &lp->host_stats;
fcoe_stats = &lport->host_stats;
memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
jiffies_to_timespec(jiffies, &v0);
jiffies_to_timespec(lp->boot_time, &v1);
jiffies_to_timespec(lport->boot_time, &v1);
fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
for_each_possible_cpu(cpu) {
struct fcoe_dev_stats *stats;
stats = per_cpu_ptr(lp->dev_stats, cpu);
stats = per_cpu_ptr(lport->dev_stats, cpu);
fcoe_stats->tx_frames += stats->TxFrames;
fcoe_stats->tx_words += stats->TxWords;
......@@ -309,11 +330,14 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
}
EXPORT_SYMBOL(fc_get_host_stats);
/*
* Fill in FLOGI command for request.
/**
* fc_lport_flogi_fill() - Fill in FLOGI command for request
* @lport: The local port the FLOGI is for
* @flogi: The FLOGI command
* @op: The opcode
*/
static void
fc_lport_flogi_fill(struct fc_lport *lport, struct fc_els_flogi *flogi,
static void fc_lport_flogi_fill(struct fc_lport *lport,
struct fc_els_flogi *flogi,
unsigned int op)
{
struct fc_els_csp *sp;
......@@ -342,8 +366,10 @@ fc_lport_flogi_fill(struct fc_lport *lport, struct fc_els_flogi *flogi,
}
}
/*
* Add a supported FC-4 type.
/**
* fc_lport_add_fc4_type() - Add a supported FC-4 type to a local port
* @lport: The local port to add a new FC-4 type to
* @type: The new FC-4 type
*/
static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
{
......@@ -355,9 +381,9 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
/**
* fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.
* @sp: The sequence in the RLIR exchange
* @fp: The RLIR request frame
* @lport: Fibre Channel local port recieving the RLIR
* @sp: current sequence in the RLIR exchange
* @fp: RLIR request frame
*
* Locking Note: The lport lock is expected to be held before calling
* this function.
......@@ -374,9 +400,9 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_lport_recv_echo_req() - Handle received ECHO request
* @lport: Fibre Channel local port recieving the ECHO
* @sp: current sequence in the ECHO exchange
* @sp: The sequence in the ECHO exchange
* @fp: ECHO request frame
* @lport: The local port recieving the ECHO
*
* Locking Note: The lport lock is expected to be held before calling
* this function.
......@@ -483,9 +509,9 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
/**
* fc_lport_recv_logo_req() - Handle received fabric LOGO request
* @lport: Fibre Channel local port recieving the LOGO
* @sp: current sequence in the LOGO exchange
* @fp: LOGO request frame
* @sp: The sequence in the LOGO exchange
* @fp: The LOGO request frame
* @lport: The local port recieving the LOGO
*
* Locking Note: The lport lock is exected to be held before calling
* this function.
......@@ -500,7 +526,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_fabric_login() - Start the lport state machine
* @lport: The lport that should log into the fabric
* @lport: The local port that should log into the fabric
*
* Locking Note: This function should not be called
* with the lport lock held.
......@@ -538,7 +564,7 @@ void __fc_linkup(struct fc_lport *lport)
/**
* fc_linkup() - Handler for transport linkup events
* @lport: The lport whose link is up
* @lport: The local port whose link is up
*/
void fc_linkup(struct fc_lport *lport)
{
......@@ -568,7 +594,7 @@ void __fc_linkdown(struct fc_lport *lport)
/**
* fc_linkdown() - Handler for transport linkdown events
* @lport: The lport whose link is down
* @lport: The local port whose link is down
*/
void fc_linkdown(struct fc_lport *lport)
{
......@@ -583,7 +609,7 @@ EXPORT_SYMBOL(fc_linkdown);
/**
* fc_fabric_logoff() - Logout of the fabric
* @lport: fc_lport pointer to logoff the fabric
* @lport: The local port to logoff the fabric
*
* Return value:
* 0 for success, -1 for failure
......@@ -592,8 +618,8 @@ int fc_fabric_logoff(struct fc_lport *lport)
{
lport->tt.disc_stop_final(lport);
mutex_lock(&lport->lp_mutex);
if (lport->dns_rp)
lport->tt.rport_logoff(lport->dns_rp);
if (lport->dns_rdata)
lport->tt.rport_logoff(lport->dns_rdata);
mutex_unlock(&lport->lp_mutex);
lport->tt.rport_flush_queue();
mutex_lock(&lport->lp_mutex);
......@@ -605,11 +631,9 @@ int fc_fabric_logoff(struct fc_lport *lport)
EXPORT_SYMBOL(fc_fabric_logoff);
/**
* fc_lport_destroy() - unregister a fc_lport
* @lport: fc_lport pointer to unregister
* fc_lport_destroy() - Unregister a fc_lport
* @lport: The local port to unregister
*
* Return value:
* None
* Note:
* exit routine for fc_lport instance
* clean-up all the allocated memory
......@@ -632,13 +656,9 @@ int fc_lport_destroy(struct fc_lport *lport)
EXPORT_SYMBOL(fc_lport_destroy);
/**
* fc_set_mfs() - sets up the mfs for the corresponding fc_lport
* @lport: fc_lport pointer to unregister
* @mfs: the new mfs for fc_lport
*
* Set mfs for the given fc_lport to the new mfs.
*
* Return: 0 for success
* fc_set_mfs() - Set the maximum frame size for a local port
* @lport: The local port to set the MFS for
* @mfs: The new MFS
*/
int fc_set_mfs(struct fc_lport *lport, u32 mfs)
{
......@@ -669,7 +689,7 @@ EXPORT_SYMBOL(fc_set_mfs);
/**
* fc_lport_disc_callback() - Callback for discovery events
* @lport: FC local port
* @lport: The local port receiving the event
* @event: The discovery event
*/
void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
......@@ -693,7 +713,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
/**
* fc_rport_enter_ready() - Enter the ready state and start discovery
* @lport: Fibre Channel local port that is ready
* @lport: The local port that is ready
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -708,15 +728,15 @@ static void fc_lport_enter_ready(struct fc_lport *lport)
fc_vport_set_state(lport->vport, FC_VPORT_ACTIVE);
fc_vports_linkchange(lport);
if (!lport->ptp_rp)
if (!lport->ptp_rdata)
lport->tt.disc_start(fc_lport_disc_callback, lport);
}
/**
* fc_lport_recv_flogi_req() - Receive a FLOGI request
* @sp_in: The sequence the FLOGI is on
* @rx_fp: The frame the FLOGI is in
* @lport: The lport that recieved the request
* @rx_fp: The FLOGI frame
* @lport: The local port that recieved the request
*
* A received FLOGI request indicates a point-to-point connection.
* Accept it with the common service parameters indicating our N port.
......@@ -802,9 +822,9 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
/**
* fc_lport_recv_req() - The generic lport request handler
* @lport: The lport that received the request
* @lport: The local port that received the request
* @sp: The sequence the request is on
* @fp: The frame the request is in
* @fp: The request frame
*
* This function will see if the lport handles the request or
* if an rport should handle the request.
......@@ -872,8 +892,8 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
}
/**
* fc_lport_reset() - Reset an lport
* @lport: The lport which should be reset
* fc_lport_reset() - Reset a local port
* @lport: The local port which should be reset
*
* Locking Note: This functions should not be called with the
* lport lock held.
......@@ -889,18 +909,18 @@ int fc_lport_reset(struct fc_lport *lport)
EXPORT_SYMBOL(fc_lport_reset);
/**
* fc_lport_reset_locked() - Reset the local port
* @lport: Fibre Channel local port to be reset
* fc_lport_reset_locked() - Reset the local port w/ the lport lock held
* @lport: The local port to be reset
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
*/
static void fc_lport_reset_locked(struct fc_lport *lport)
{
if (lport->dns_rp)
lport->tt.rport_logoff(lport->dns_rp);
if (lport->dns_rdata)
lport->tt.rport_logoff(lport->dns_rdata);
lport->ptp_rp = NULL;
lport->ptp_rdata = NULL;
lport->tt.disc_stop(lport);
......@@ -911,7 +931,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport)
/**
* fc_lport_enter_reset() - Reset the local port
* @lport: Fibre Channel local port to be reset
* @lport: The local port to be reset
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -935,8 +955,8 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
}
/**
* fc_lport_enter_disabled() - disable the local port
* @lport: Fibre Channel local port to be reset
* fc_lport_enter_disabled() - Disable the local port
* @lport: The local port to be reset
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -953,8 +973,8 @@ static void fc_lport_enter_disabled(struct fc_lport *lport)
/**
* fc_lport_error() - Handler for any errors
* @lport: The fc_lport object
* @fp: The frame pointer
* @lport: The local port that the error was on
* @fp: The error code encoded in a frame pointer
*
* If the error was caused by a resource allocation failure
* then wait for half a second and retry, otherwise retry
......@@ -1008,7 +1028,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
* @lp_arg: Fibre Channel host port instance
*
* Locking Note: This function will be called without the lport lock
* held, but it will lock, call an _enter_* function or fc_lport_error
* held, but it will lock, call an _enter_* function or fc_lport_error()
* and then unlock the lport.
*/
static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
......@@ -1119,8 +1139,8 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_lport_enter_scr() - Send a State Change Register (SCR) request
* @lport: Fibre Channel local port to register for state changes
* fc_lport_enter_scr() - Send a SCR (State Change Register) request
* @lport: The local port to register for state changes
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -1212,8 +1232,8 @@ static struct fc_rport_operations fc_lport_rport_ops = {
};
/**
* fc_rport_enter_dns() - Create a rport to the name server
* @lport: Fibre Channel local port requesting a rport for the name server
* fc_rport_enter_dns() - Create a fc_rport for the name server
* @lport: The local port requesting a remote port for the name server
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -1242,8 +1262,8 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
}
/**
* fc_lport_timeout() - Handler for the retry_work timer.
* @work: The work struct of the fc_lport
* fc_lport_timeout() - Handler for the retry_work timer
* @work: The work struct of the local port
*/
static void fc_lport_timeout(struct work_struct *work)
{
......@@ -1287,12 +1307,12 @@ static void fc_lport_timeout(struct work_struct *work)
/**
* fc_lport_logo_resp() - Handle response to LOGO request
* @sp: current sequence in LOGO exchange
* @fp: response frame
* @lp_arg: Fibre Channel lport port instance that sent the LOGO request
* @sp: The sequence that the LOGO was on
* @fp: The LOGO frame
* @lp_arg: The lport port that received the LOGO request
*
* Locking Note: This function will be called without the lport lock
* held, but it will lock, call an _enter_* function or fc_lport_error
* held, but it will lock, call an _enter_* function or fc_lport_error()
* and then unlock the lport.
*/
void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
......@@ -1336,7 +1356,7 @@ EXPORT_SYMBOL(fc_lport_logo_resp);
/**
* fc_rport_enter_logo() - Logout of the fabric
* @lport: Fibre Channel local port to be logged out
* @lport: The local port to be logged out
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -1365,12 +1385,12 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
/**
* fc_lport_flogi_resp() - Handle response to FLOGI request
* @sp: current sequence in FLOGI exchange
* @fp: response frame
* @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
* @sp: The sequence that the FLOGI was on
* @fp: The FLOGI response frame
* @lp_arg: The lport port that received the FLOGI response
*
* Locking Note: This function will be called without the lport lock
* held, but it will lock, call an _enter_* function or fc_lport_error
* held, but it will lock, call an _enter_* function or fc_lport_error()
* and then unlock the lport.
*/
void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
......@@ -1484,7 +1504,10 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
fc_lport_error(lport, NULL);
}
/* Configure a fc_lport */
/**
* fc_lport_config() - Configure a fc_lport
* @lport: The local port to be configured
*/
int fc_lport_config(struct fc_lport *lport)
{
INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
......@@ -1499,6 +1522,10 @@ int fc_lport_config(struct fc_lport *lport)
}
EXPORT_SYMBOL(fc_lport_config);
/**
* fc_lport_init() - Initialize the lport layer for a local port
* @lport: The local port to initialize the exchange layer for
*/
int fc_lport_init(struct fc_lport *lport)
{
if (!lport->tt.lport_recv)
......@@ -1533,10 +1560,10 @@ int fc_lport_init(struct fc_lport *lport)
EXPORT_SYMBOL(fc_lport_init);
/**
* fc_lport_bsg_resp() - The common response handler for fc pass-thru requests
* @sp: current sequence in the fc pass-thru request exchange
* @fp: received response frame
* @info_arg: pointer to struct fc_bsg_info
* fc_lport_bsg_resp() - The common response handler for FC Passthrough requests
* @sp: The sequence for the FC Passthrough response
* @fp: The response frame
* @info_arg: The BSG info that the response is for
*/
static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
void *info_arg)
......@@ -1596,10 +1623,10 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_lport_els_request() - Send ELS pass-thru request
* @job: The bsg fc pass-thru job structure
* fc_lport_els_request() - Send ELS passthrough request
* @job: The BSG Passthrough job
* @lport: The local port sending the request
* @did: The destination port id.
* @did: The destination port id
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -1656,11 +1683,11 @@ static int fc_lport_els_request(struct fc_bsg_job *job,
}
/**
* fc_lport_ct_request() - Send CT pass-thru request
* @job: The bsg fc pass-thru job structure
* fc_lport_ct_request() - Send CT Passthrough request
* @job: The BSG Passthrough job
* @lport: The local port sending the request
* @did: The destination FC-ID
* @tov: The time to wait for a response
* @tov: The timeout period to wait for the response
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
......@@ -1717,8 +1744,8 @@ static int fc_lport_ct_request(struct fc_bsg_job *job,
/**
* fc_lport_bsg_request() - The common entry point for sending
* fc pass-thru requests
* @job: The fc pass-thru job structure
* FC Passthrough requests
* @job: The BSG passthrough job
*/
int fc_lport_bsg_request(struct fc_bsg_job *job)
{
......@@ -1759,7 +1786,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
case FC_BSG_HST_CT:
did = ntoh24(job->request->rqst_data.h_ct.port_id);
if (did == FC_FID_DIR_SERV)
rdata = lport->dns_rp;
rdata = lport->dns_rdata;
else
rdata = lport->tt.rport_lookup(lport, did);
......
......@@ -92,9 +92,9 @@ static const char *fc_rport_state_names[] = {
};
/**
* fc_rport_lookup() - lookup a remote port by port_id
* @lport: Fibre Channel host port instance
* @port_id: remote port port_id to match
* fc_rport_lookup() - Lookup a remote port by port_id
* @lport: The local port to lookup the remote port on
* @port_id: The remote port ID to look up
*/
static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
u32 port_id)
......@@ -109,8 +109,10 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
/**
* fc_rport_create() - Create a new remote port
* @lport: The local port that the new remote port is for
* @port_id: The port ID for the new remote port
* @lport: The local port this remote port will be associated with
* @ids: The identifiers for the new remote port
*
* The remote port will start in the INIT state.
*
* Locking note: must be called with the disc_mutex held.
*/
......@@ -149,8 +151,8 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
}
/**
* fc_rport_destroy() - free a remote port after last reference is released.
* @kref: pointer to kref inside struct fc_rport_priv
* fc_rport_destroy() - Free a remote port after last reference is released
* @kref: The remote port's kref
*/
static void fc_rport_destroy(struct kref *kref)
{
......@@ -161,8 +163,8 @@ static void fc_rport_destroy(struct kref *kref)
}
/**
* fc_rport_state() - return a string for the state the rport is in
* @rdata: remote port private data
* fc_rport_state() - Return a string identifying the remote port's state
* @rdata: The remote port
*/
static const char *fc_rport_state(struct fc_rport_priv *rdata)
{
......@@ -175,9 +177,9 @@ static const char *fc_rport_state(struct fc_rport_priv *rdata)
}
/**
* fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds.
* @rport: Pointer to Fibre Channel remote port structure
* @timeout: timeout in seconds
* fc_set_rport_loss_tmo() - Set the remote port loss timeout
* @rport: The remote port that gets a new timeout value
* @timeout: The new timeout value (in seconds)
*/
void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
{
......@@ -189,9 +191,11 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
EXPORT_SYMBOL(fc_set_rport_loss_tmo);
/**
* fc_plogi_get_maxframe() - Get max payload from the common service parameters
* @flp: FLOGI payload structure
* @maxval: upper limit, may be less than what is in the service parameters
* fc_plogi_get_maxframe() - Get the maximum payload from the common service
* parameters in a FLOGI frame
* @flp: The FLOGI payload
* @maxval: The maximum frame size upper limit; this may be less than what
* is in the service parameters
*/
static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,
unsigned int maxval)
......@@ -212,9 +216,9 @@ static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,
}
/**
* fc_rport_state_enter() - Change the rport's state
* @rdata: The rport whose state should change
* @new: The new state of the rport
* fc_rport_state_enter() - Change the state of a remote port
* @rdata: The remote port whose state should change
* @new: The new state
*
* Locking Note: Called with the rport lock held
*/
......@@ -226,12 +230,16 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata,
rdata->rp_state = new;
}
/**
* fc_rport_work() - Handler for remote port events in the rport_event_queue
* @work: Handle to the remote port being dequeued
*/
static void fc_rport_work(struct work_struct *work)
{
u32 port_id;
struct fc_rport_priv *rdata =
container_of(work, struct fc_rport_priv, event_work);
struct fc_rport_libfc_priv *rp;
struct fc_rport_libfc_priv *rpriv;
enum fc_rport_event event;
struct fc_lport *lport = rdata->local_port;
struct fc_rport_operations *rport_ops;
......@@ -268,12 +276,12 @@ static void fc_rport_work(struct work_struct *work)
rport->maxframe_size = rdata->maxframe_size;
rport->supported_classes = rdata->supported_classes;
rp = rport->dd_data;
rp->local_port = lport;
rp->rp_state = rdata->rp_state;
rp->flags = rdata->flags;
rp->e_d_tov = rdata->e_d_tov;
rp->r_a_tov = rdata->r_a_tov;
rpriv = rport->dd_data;
rpriv->local_port = lport;
rpriv->rp_state = rdata->rp_state;
rpriv->flags = rdata->flags;
rpriv->e_d_tov = rdata->e_d_tov;
rpriv->r_a_tov = rdata->r_a_tov;
mutex_unlock(&rdata->rp_mutex);
if (rport_ops && rport_ops->event_callback) {
......@@ -319,8 +327,8 @@ static void fc_rport_work(struct work_struct *work)
lport->tt.exch_mgr_reset(lport, port_id, 0);
if (rport) {
rp = rport->dd_data;
rp->rp_state = RPORT_ST_DELETE;
rpriv = rport->dd_data;
rpriv->rp_state = RPORT_ST_DELETE;
mutex_lock(&rdata->rp_mutex);
rdata->rport = NULL;
mutex_unlock(&rdata->rp_mutex);
......@@ -343,7 +351,7 @@ static void fc_rport_work(struct work_struct *work)
/**
* fc_rport_login() - Start the remote port login state machine
* @rdata: private remote port
* @rdata: The remote port to be logged in to
*
* Locking Note: Called without the rport lock held. This
* function will hold the rport lock, call an _enter_*
......@@ -379,9 +387,9 @@ int fc_rport_login(struct fc_rport_priv *rdata)
}
/**
* fc_rport_enter_delete() - schedule a remote port to be deleted.
* @rdata: private remote port
* @event: event to report as the reason for deletion
* fc_rport_enter_delete() - Schedule a remote port to be deleted
* @rdata: The remote port to be deleted
* @event: The event to report as the reason for deletion
*
* Locking Note: Called with the rport lock held.
*
......@@ -408,8 +416,8 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
}
/**
* fc_rport_logoff() - Logoff and remove an rport
* @rdata: private remote port
* fc_rport_logoff() - Logoff and remove a remote port
* @rdata: The remote port to be logged off of
*
* Locking Note: Called without the rport lock held. This
* function will hold the rport lock, call an _enter_*
......@@ -442,8 +450,8 @@ int fc_rport_logoff(struct fc_rport_priv *rdata)
}
/**
* fc_rport_enter_ready() - The rport is ready
* @rdata: private remote port
* fc_rport_enter_ready() - Transition to the RPORT_ST_READY state
* @rdata: The remote port that is ready
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
......@@ -460,8 +468,8 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
}
/**
* fc_rport_timeout() - Handler for the retry_work timer.
* @work: The work struct of the fc_rport_priv
* fc_rport_timeout() - Handler for the retry_work timer
* @work: Handle to the remote port that has timed out
*
* Locking Note: Called without the rport lock held. This
* function will hold the rport lock, call an _enter_*
......@@ -502,8 +510,8 @@ static void fc_rport_timeout(struct work_struct *work)
/**
* fc_rport_error() - Error handler, called once retries have been exhausted
* @rdata: private remote port
* @fp: The frame pointer
* @rdata: The remote port the error is happened on
* @fp: The error code encapsulated in a frame pointer
*
* Locking Note: The rport lock is expected to be held before
* calling this routine
......@@ -535,9 +543,9 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
}
/**
* fc_rport_error_retry() - Error handler when retries are desired
* @rdata: private remote port data
* @fp: The frame pointer
* fc_rport_error_retry() - Handler for remote port state retries
* @rdata: The remote port whose state is to be retried
* @fp: The error code encapsulated in a frame pointer
*
* If the error was an exchange timeout retry immediately,
* otherwise wait for E_D_TOV.
......@@ -569,10 +577,10 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
}
/**
* fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response
* @sp: current sequence in the PLOGI exchange
* @fp: response frame
* @rdata_arg: private remote port data
* fc_rport_plogi_recv_resp() - Handler for ELS PLOGI responses
* @sp: The sequence the PLOGI is on
* @fp: The PLOGI response frame
* @rdata_arg: The remote port that sent the PLOGI response
*
* Locking Note: This function will be called without the rport lock
* held, but it will lock, call an _enter_* function or fc_rport_error
......@@ -635,8 +643,8 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer
* @rdata: private remote port data
* fc_rport_enter_plogi() - Send Port Login (PLOGI) request
* @rdata: The remote port to send a PLOGI to
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
......@@ -668,9 +676,9 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
/**
* fc_rport_prli_resp() - Process Login (PRLI) response handler
* @sp: current sequence in the PRLI exchange
* @fp: response frame
* @rdata_arg: private remote port data
* @sp: The sequence the PRLI response was on
* @fp: The PRLI response frame
* @rdata_arg: The remote port that sent the PRLI response
*
* Locking Note: This function will be called without the rport lock
* held, but it will lock, call an _enter_* function or fc_rport_error
......@@ -739,10 +747,10 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_rport_logo_resp() - Logout (LOGO) response handler
* @sp: current sequence in the LOGO exchange
* @fp: response frame
* @rdata_arg: private remote port data
* fc_rport_logo_resp() - Handler for logout (LOGO) responses
* @sp: The sequence the LOGO was on
* @fp: The LOGO response frame
* @rdata_arg: The remote port that sent the LOGO response
*
* Locking Note: This function will be called without the rport lock
* held, but it will lock, call an _enter_* function or fc_rport_error
......@@ -785,8 +793,8 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_rport_enter_prli() - Send Process Login (PRLI) request to peer
* @rdata: private remote port data
* fc_rport_enter_prli() - Send Process Login (PRLI) request
* @rdata: The remote port to send the PRLI request to
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
......@@ -828,10 +836,10 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
}
/**
* fc_rport_els_rtv_resp() - Request Timeout Value response handler
* @sp: current sequence in the RTV exchange
* @fp: response frame
* @rdata_arg: private remote port data
* fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses
* @sp: The sequence the RTV was on
* @fp: The RTV response frame
* @rdata_arg: The remote port that sent the RTV response
*
* Many targets don't seem to support this.
*
......@@ -894,8 +902,8 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer
* @rdata: private remote port data
* fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request
* @rdata: The remote port to send the RTV request to
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
......@@ -924,8 +932,8 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
}
/**
* fc_rport_enter_logo() - Send Logout (LOGO) request to peer
* @rdata: private remote port data
* fc_rport_enter_logo() - Send a logout (LOGO) request
* @rdata: The remote port to send the LOGO request to
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
......@@ -954,10 +962,10 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
}
/**
* fc_rport_els_adisc_resp() - Address Discovery response handler
* @sp: current sequence in the ADISC exchange
* @fp: response frame
* @rdata_arg: remote port private.
* fc_rport_els_adisc_resp() - Handler for Address Discovery (ADISC) responses
* @sp: The sequence the ADISC response was on
* @fp: The ADISC response frame
* @rdata_arg: The remote port that sent the ADISC response
*
* Locking Note: This function will be called without the rport lock
* held, but it will lock, call an _enter_* function or fc_rport_error
......@@ -1012,8 +1020,8 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_rport_enter_adisc() - Send Address Discover (ADISC) request to peer
* @rdata: remote port private data
* fc_rport_enter_adisc() - Send Address Discover (ADISC) request
* @rdata: The remote port to send the ADISC request to
*
* Locking Note: The rport lock is expected to be held before calling
* this routine.
......@@ -1041,10 +1049,10 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
}
/**
* fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request
* @rdata: remote port private
* @sp: current sequence in the ADISC exchange
* @in_fp: ADISC request frame
* fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests
* @rdata: The remote port that sent the ADISC request
* @sp: The sequence the ADISC request was on
* @in_fp: The ADISC request frame
*
* Locking Note: Called with the lport and rport locks held.
*/
......@@ -1085,10 +1093,10 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
}
/**
* fc_rport_recv_els_req() - handle a validated ELS request.
* @lport: Fibre Channel local port
* @sp: current sequence in the PLOGI exchange
* @fp: response frame
* fc_rport_recv_els_req() - Handler for validated ELS requests
* @lport: The local port that received the ELS request
* @sp: The sequence that the ELS request was on
* @fp: The ELS request frame
*
* Handle incoming ELS requests that require port login.
* The ELS opcode has already been validated by the caller.
......@@ -1160,10 +1168,10 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
}
/**
* fc_rport_recv_req() - Handle a received ELS request from a rport
* @sp: current sequence in the PLOGI exchange
* @fp: response frame
* @lport: Fibre Channel local port
* fc_rport_recv_req() - Handler for requests
* @sp: The sequence the request was on
* @fp: The request frame
* @lport: The local port that received the request
*
* Locking Note: Called with the lport lock held.
*/
......@@ -1203,10 +1211,10 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
}
/**
* fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request
* @lport: local port
* @sp: current sequence in the PLOGI exchange
* @fp: PLOGI request frame
* fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests
* @lport: The local port that received the PLOGI request
* @sp: The sequence that the PLOGI request was on
* @rx_fp: The PLOGI request frame
*
* Locking Note: The rport lock is held before calling this function.
*/
......@@ -1328,10 +1336,10 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
}
/**
* fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request
* @rdata: private remote port data
* @sp: current sequence in the PRLI exchange
* @fp: PRLI request frame
* fc_rport_recv_prli_req() - Handler for process login (PRLI) requests
* @rdata: The remote port that sent the PRLI request
* @sp: The sequence that the PRLI was on
* @rx_fp: The PRLI request frame
*
* Locking Note: The rport lock is exected to be held before calling
* this function.
......@@ -1485,10 +1493,10 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
}
/**
* fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request
* @rdata: private remote port data
* @sp: current sequence in the PRLO exchange
* @fp: PRLO request frame
* fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests
* @rdata: The remote port that sent the PRLO request
* @sp: The sequence that the PRLO was on
* @fp: The PRLO request frame
*
* Locking Note: The rport lock is exected to be held before calling
* this function.
......@@ -1515,10 +1523,10 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
}
/**
* fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request
* @lport: local port.
* @sp: current sequence in the LOGO exchange
* @fp: LOGO request frame
* fc_rport_recv_logo_req() - Handler for logout (LOGO) requests
* @lport: The local port that received the LOGO request
* @sp: The sequence that the LOGO request was on
* @fp: The LOGO request frame
*
* Locking Note: The rport lock is exected to be held before calling
* this function.
......@@ -1559,11 +1567,18 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport,
fc_frame_free(fp);
}
/**
* fc_rport_flush_queue() - Flush the rport_event_queue
*/
static void fc_rport_flush_queue(void)
{
flush_workqueue(rport_event_queue);
}
/**
* fc_rport_init() - Initialize the remote port layer for a local port
* @lport: The local port to initialize the remote port layer for
*/
int fc_rport_init(struct fc_lport *lport)
{
if (!lport->tt.rport_lookup)
......@@ -1591,7 +1606,10 @@ int fc_rport_init(struct fc_lport *lport)
}
EXPORT_SYMBOL(fc_rport_init);
int fc_setup_rport(void)
/**
* fc_setup_rport() - Initialize the rport_event_queue
*/
int fc_setup_rport()
{
rport_event_queue = create_singlethread_workqueue("fc_rport_eq");
if (!rport_event_queue)
......@@ -1599,15 +1617,22 @@ int fc_setup_rport(void)
return 0;
}
void fc_destroy_rport(void)
/**
* fc_destroy_rport() - Destroy the rport_event_queue
*/
void fc_destroy_rport()
{
destroy_workqueue(rport_event_queue);
}
/**
* fc_rport_terminate_io() - Stop all outstanding I/O on a remote port
* @rport: The remote port whose I/O should be terminated
*/
void fc_rport_terminate_io(struct fc_rport *rport)
{
struct fc_rport_libfc_priv *rp = rport->dd_data;
struct fc_lport *lport = rp->local_port;
struct fc_rport_libfc_priv *rpriv = rport->dd_data;
struct fc_lport *lport = rpriv->local_port;
lport->tt.exch_mgr_reset(lport, 0, rport->port_id);
lport->tt.exch_mgr_reset(lport, rport->port_id, 0);
......
......@@ -55,8 +55,17 @@
p[2] = ((v) & 0xFF); \
} while (0)
/*
* FC HBA status
/**
* enum fc_lport_state - Local port states
* @LPORT_ST_DISABLED: Disabled
* @LPORT_ST_FLOGI: Fabric login (FLOGI) sent
* @LPORT_ST_DNS: Waiting for name server remote port to become ready
* @LPORT_ST_RPN_ID: Register port name by ID (RPN_ID) sent
* @LPORT_ST_RFT_ID: Register Fibre Channel types by ID (RFT_ID) sent
* @LPORT_ST_SCR: State Change Register (SCR) sent
* @LPORT_ST_READY: Ready for use
* @LPORT_ST_LOGO: Local port logout (LOGO) sent
* @LPORT_ST_RESET: Local port reset
*/
enum fc_lport_state {
LPORT_ST_DISABLED = 0,
......@@ -78,16 +87,28 @@ enum fc_disc_event {
DISC_EV_FAILED
};
/**
* enum fc_rport_state - Remote port states
* @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: Remote port logout (LOGO) sent
* @RPORT_ST_ADISC: Discover Address sent
* @RPORT_ST_DELETE: Remote port being deleted
* @RPORT_ST_RESTART: Remote port being deleted and will restart
*/
enum fc_rport_state {
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_ADISC, /* Discover Address sent */
RPORT_ST_DELETE, /* port being deleted */
RPORT_ST_RESTART, /* remote port being deleted and will restart */
RPORT_ST_INIT,
RPORT_ST_PLOGI,
RPORT_ST_PRLI,
RPORT_ST_RTV,
RPORT_ST_READY,
RPORT_ST_LOGO,
RPORT_ST_ADISC,
RPORT_ST_DELETE,
RPORT_ST_RESTART,
};
/**
......@@ -104,6 +125,14 @@ struct fc_disc_port {
u32 port_id;
};
/**
* enum fc_rport_event - Remote port events
* @RPORT_EV_NONE: No event
* @RPORT_EV_READY: Remote port is ready for use
* @RPORT_EV_FAILED: State machine failed, remote port is not ready
* @RPORT_EV_STOP: Remote port has been stopped
* @RPORT_EV_LOGO: Remote port logout (LOGO) sent
*/
enum fc_rport_event {
RPORT_EV_NONE = 0,
RPORT_EV_READY,
......@@ -114,6 +143,10 @@ enum fc_rport_event {
struct fc_rport_priv;
/**
* struct fc_rport_operations - Operations for a remote port
* @event_callback: Function to be called for remote port events
*/
struct fc_rport_operations {
void (*event_callback)(struct fc_lport *, struct fc_rport_priv *,
enum fc_rport_event);
......@@ -121,11 +154,11 @@ struct fc_rport_operations {
/**
* 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.
* @local_port: The associated local port
* @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)
* @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;
......@@ -138,22 +171,23 @@ struct fc_rport_libfc_priv {
};
/**
* 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
* struct fc_rport_priv - libfc remote port and discovery info
* @local_port: The associated local port
* @rport: The FC transport remote port
* @kref: Reference counter
* @rp_state: Enumeration that tracks progress of PLOGI, PRLI,
* and RTV exchanges
* @ids: The 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)
* @rp_mutex: mutex protects rport
* @retry_work:
* @event_callback: Callback for rport READY, FAILED or LOGO
* @max_seq: Maximum number of concurrent sequences
* @disc_id: The discovery identifier
* @maxframe_size: The maximum frame size
* @retries: The retry count for the current state
* @e_d_tov: Error detect timeout value (in msec)
* @r_a_tov: Resource allocation timeout value (in msec)
* @rp_mutex: The mutex that protects the remote port
* @retry_work: Handle for retries
* @event_callback: Callback when READY, FAILED or LOGO states complete
*/
struct fc_rport_priv {
struct fc_lport *local_port;
......@@ -177,8 +211,24 @@ struct fc_rport_priv {
u32 supported_classes;
};
/*
* fcoe stats structure
/**
* struct fcoe_dev_stats - fcoe stats structure
* @SecondsSinceLastReset: Seconds since the last reset
* @TxFrames: Number of transmitted frames
* @TxWords: Number of transmitted words
* @RxFrames: Number of received frames
* @RxWords: Number of received words
* @ErrorFrames: Number of received error frames
* @DumpedFrames: Number of dumped frames
* @LinkFailureCount: Number of link failures
* @LossOfSignalCount: Number for signal losses
* @InvalidTxWordCount: Number of invalid transmitted words
* @InvalidCRCCount: Number of invalid CRCs
* @InputRequests: Number of input requests
* @OutputRequests: Number of output requests
* @ControlRequests: Number of control requests
* @InputMegabytes: Number of received megabytes
* @OutputMegabytes: Number of transmitted megabytes
*/
struct fcoe_dev_stats {
u64 SecondsSinceLastReset;
......@@ -199,10 +249,13 @@ struct fcoe_dev_stats {
u64 OutputMegabytes;
};
/*
* els data is used for passing ELS respone specific
* data to send ELS response mainly using infomation
* in exchange and sequence in EM layer.
/**
* struct fc_seq_els_data - ELS data used for passing ELS specific responses
* @fp: The ELS frame
* @reason: The reason for rejection
* @explan: The explaination of the rejection
*
* Mainly used by the exchange manager layer.
*/
struct fc_seq_els_data {
struct fc_frame *fp;
......@@ -210,77 +263,87 @@ struct fc_seq_els_data {
enum fc_els_rjt_explan explan;
};
/*
* FCP request structure, one for each scsi cmd request
/**
* struct fc_fcp_pkt - FCP request structure (one for each scsi_cmnd request)
* @lp: The associated local port
* @state: The state of the I/O
* @tgt_flags: Target's flags
* @ref_cnt: Reference count
* @scsi_pkt_lock: Lock to protect the SCSI packet (must be taken before the
* host_lock if both are to be held at the same time)
* @cmd: The SCSI command (set and clear with the host_lock held)
* @list: Tracks queued commands (accessed with the host_lock held)
* @timer: The command timer
* @tm_done: Completion indicator
* @wait_for_comp: Indicator to wait for completion of the I/O (in jiffies)
* @start_time: Timestamp indicating the start of the I/O (in jiffies)
* @end_time: Timestamp indicating the end of the I/O (in jiffies)
* @last_pkt_time: Timestamp of the last frame received (in jiffies)
* @data_len: The length of the data
* @cdb_cmd: The CDB command
* @xfer_len: The transfer length
* @xfer_ddp: Indicates if this transfer used DDP (XID of the exchange
* will be set here if DDP was setup)
* @xfer_contig_end: The offset into the buffer if the buffer is contiguous
* (Tx and Rx)
* @max_payload: The maximum payload size (in bytes)
* @io_status: SCSI result (upper 24 bits)
* @cdb_status: CDB status
* @status_code: FCP I/O status
* @scsi_comp_flags: Completion flags (bit 3 Underrun bit 2: overrun)
* @req_flags: Request flags (bit 0: read bit:1 write)
* @scsi_resid: SCSI residule length
* @rport: The remote port that the SCSI command is targeted at
* @seq_ptr: The sequence that will carry the SCSI command
* @recov_retry: Number of recovery retries
* @recov_seq: The sequence for REC or SRR
*/
struct fc_fcp_pkt {
/*
* housekeeping stuff
*/
struct fc_lport *lp; /* handle to hba struct */
u16 state; /* scsi_pkt state state */
u16 tgt_flags; /* target flags */
atomic_t ref_cnt; /* fcp pkt ref count */
spinlock_t scsi_pkt_lock; /* Must be taken before the host lock
* if both are held at the same time */
/*
* SCSI I/O related stuff
*/
struct scsi_cmnd *cmd; /* scsi command pointer. set/clear
* under host lock */
struct list_head list; /* tracks queued commands. access under
* host lock */
/*
* timeout related stuff
*/
struct timer_list timer; /* command timer */
/* Housekeeping information */
struct fc_lport *lp;
u16 state;
u16 tgt_flags;
atomic_t ref_cnt;
spinlock_t scsi_pkt_lock;
/* SCSI I/O related information */
struct scsi_cmnd *cmd;
struct list_head list;
/* Timeout related information */
struct timer_list timer;
struct completion tm_done;
int wait_for_comp;
unsigned long start_time; /* start jiffie */
unsigned long end_time; /* end jiffie */
unsigned long last_pkt_time; /* jiffies of last frame received */
unsigned long start_time;
unsigned long end_time;
unsigned long last_pkt_time;
/*
* scsi cmd and data transfer information
*/
/* SCSI command and data transfer information */
u32 data_len;
/*
* transport related veriables
*/
/* Transport related veriables */
struct fcp_cmnd cdb_cmd;
size_t xfer_len;
u16 xfer_ddp; /* this xfer is ddped */
u32 xfer_contig_end; /* offset of end of contiguous xfer */
u16 max_payload; /* max payload size in bytes */
u16 xfer_ddp;
u32 xfer_contig_end;
u16 max_payload;
/*
* scsi/fcp return status
*/
u32 io_status; /* SCSI result upper 24 bits */
/* SCSI/FCP return status */
u32 io_status;
u8 cdb_status;
u8 status_code; /* FCP I/O status */
/* bit 3 Underrun bit 2: overrun */
u8 status_code;
u8 scsi_comp_flags;
u32 req_flags; /* bit 0: read bit:1 write */
u32 scsi_resid; /* residule length */
u32 req_flags;
u32 scsi_resid;
struct fc_rport *rport; /* remote port pointer */
struct fc_seq *seq_ptr; /* current sequence pointer */
/*
* Error Processing
*/
u8 recov_retry; /* count of recovery retries */
struct fc_seq *recov_seq; /* sequence for REC or SRR */
/* Associated structures */
struct fc_rport *rport;
struct fc_seq *seq_ptr;
/* Error Processing information */
u8 recov_retry;
struct fc_seq *recov_seq;
};
/*
* FC_FCP HELPER FUNCTIONS
*****************************/
static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp)
{
if (fsp && fsp->cmd)
return fsp->cmd->sc_data_direction == DMA_FROM_DEVICE;
return false;
}
/*
* Structure and function definitions for managing Fibre Channel Exchanges
......@@ -295,21 +358,49 @@ struct fc_exch_mgr;
struct fc_exch_mgr_anchor;
extern u16 fc_cpu_mask; /* cpu mask for possible cpus */
/*
* Sequence.
/**
* struct fc_seq - FC sequence
* @id: The sequence ID
* @ssb_stat: Status flags for the sequence status block (SSB)
* @cnt: Number of frames sent so far
* @rec_data: FC-4 value for REC
*/
struct fc_seq {
u8 id; /* seq ID */
u16 ssb_stat; /* status flags for sequence status block */
u16 cnt; /* frames sent so far on sequence */
u32 rec_data; /* FC-4 value for REC */
u8 id;
u16 ssb_stat;
u16 cnt;
u32 rec_data;
};
#define FC_EX_DONE (1 << 0) /* ep is completed */
#define FC_EX_RST_CLEANUP (1 << 1) /* reset is forcing completion */
/*
* Exchange.
/**
* struct fc_exch - Fibre Channel Exchange
* @em: Exchange manager
* @pool: Exchange pool
* @state: The exchange's state
* @xid: The exchange ID
* @ex_list: Handle used by the EM to track free exchanges
* @ex_lock: Lock that protects the exchange
* @ex_refcnt: Reference count
* @timeout_work: Handle for timeout handler
* @lp: The local port that this exchange is on
* @oxid: Originator's exchange ID
* @rxid: Responder's exchange ID
* @oid: Originator's FCID
* @sid: Source FCID
* @did: Destination FCID
* @esb_stat: ESB exchange status
* @r_a_tov: Resouce allocation time out value (in msecs)
* @seq_id: The next sequence ID to use
* @f_ctl: F_CTL flags for the sequence
* @fh_type: The frame type
* @class: The class of service
* @seq: The sequence in use on this exchange
* @resp: Callback for responses on this exchange
* @destructor: Called when destroying the exchange
* @arg: Passed as a void pointer to the resp() callback
*
* Locking notes: The ex_lock protects following items:
* state, esb_stat, f_ctl, seq.ssb_stat
......@@ -317,76 +408,59 @@ struct fc_seq {
* sequence allocation
*/
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 */
spinlock_t ex_lock; /* lock covering exchange state */
atomic_t ex_refcnt; /* reference counter */
struct delayed_work timeout_work; /* timer for upper level protocols */
struct fc_lport *lp; /* fc device instance */
u16 oxid; /* originator's exchange ID */
u16 rxid; /* responder's exchange ID */
u32 oid; /* originator's FCID */
u32 sid; /* source FCID */
u32 did; /* destination FCID */
u32 esb_stat; /* exchange status for ESB */
u32 r_a_tov; /* r_a_tov from rport (msec) */
u8 seq_id; /* next sequence ID to use */
u32 f_ctl; /* F_CTL flags for sequences */
u8 fh_type; /* frame type */
enum fc_class class; /* class of service */
struct fc_seq seq; /* single sequence */
/*
* Handler for responses to this current exchange.
*/
struct fc_exch_mgr *em;
struct fc_exch_pool *pool;
u32 state;
u16 xid;
struct list_head ex_list;
spinlock_t ex_lock;
atomic_t ex_refcnt;
struct delayed_work timeout_work;
struct fc_lport *lp;
u16 oxid;
u16 rxid;
u32 oid;
u32 sid;
u32 did;
u32 esb_stat;
u32 r_a_tov;
u8 seq_id;
u32 f_ctl;
u8 fh_type;
enum fc_class class;
struct fc_seq seq;
void (*resp)(struct fc_seq *, struct fc_frame *, void *);
void (*destructor)(struct fc_seq *, void *);
/*
* arg is passed as void pointer to exchange
* resp and destructor handlers
*/
void *arg;
void (*destructor)(struct fc_seq *, void *);
};
#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
struct libfc_function_template {
struct libfc_function_template {
/*
* Interface to send a FC frame
*
* STATUS: REQUIRED
*/
int (*frame_send)(struct fc_lport *lp, struct fc_frame *fp);
int (*frame_send)(struct fc_lport *, struct fc_frame *);
/*
* Interface to send ELS/CT frames
*
* STATUS: OPTIONAL
*/
struct fc_seq *(*elsct_send)(struct fc_lport *lport,
u32 did,
struct fc_frame *fp,
unsigned int op,
struct fc_seq *(*elsct_send)(struct fc_lport *, u32 did,
struct fc_frame *, unsigned int op,
void (*resp)(struct fc_seq *,
struct fc_frame *fp,
void *arg),
struct fc_frame *, void *arg),
void *arg, u32 timer_msec);
/*
* Send the FC frame payload using a new exchange and sequence.
*
* The frame pointer with some of the header's fields must be
* filled before calling exch_seq_send(), those fields are,
*
* - routing control
* - FC port did
* - FC port sid
* - FC header type
* - frame control
* - parameter or relative offset
*
* The exchange response handler is set in this routine to resp()
* function pointer. It can be called in two scenarios: if a timeout
* occurs or if a response frame is received for the exchange. The
......@@ -407,14 +481,13 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
struct fc_seq *(*exch_seq_send)(struct fc_lport *lp,
struct fc_frame *fp,
void (*resp)(struct fc_seq *sp,
struct fc_frame *fp,
void *arg),
void (*destructor)(struct fc_seq *sp,
void *arg),
void *arg, unsigned int timer_msec);
struct fc_seq *(*exch_seq_send)(struct fc_lport *, struct fc_frame *,
void (*resp)(struct fc_seq *,
struct fc_frame *,
void *),
void (*destructor)(struct fc_seq *,
void *),
void *, unsigned int timer_msec);
/*
* Sets up the DDP context for a given exchange id on the given
......@@ -422,22 +495,22 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
int (*ddp_setup)(struct fc_lport *lp, u16 xid,
struct scatterlist *sgl, unsigned int sgc);
int (*ddp_setup)(struct fc_lport *, u16, struct scatterlist *,
unsigned int);
/*
* Completes the DDP transfer and returns the length of data DDPed
* for the given exchange id.
*
* STATUS: OPTIONAL
*/
int (*ddp_done)(struct fc_lport *lp, u16 xid);
int (*ddp_done)(struct fc_lport *, u16);
/*
* Send a frame using an existing sequence and exchange.
*
* STATUS: OPTIONAL
*/
int (*seq_send)(struct fc_lport *lp, struct fc_seq *sp,
struct fc_frame *fp);
int (*seq_send)(struct fc_lport *, struct fc_seq *,
struct fc_frame *);
/*
* Send an ELS response using infomation from a previous
......@@ -445,8 +518,8 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
void (*seq_els_rsp_send)(struct fc_seq *sp, enum fc_els_cmd els_cmd,
struct fc_seq_els_data *els_data);
void (*seq_els_rsp_send)(struct fc_seq *, enum fc_els_cmd,
struct fc_seq_els_data *);
/*
* Abort an exchange and sequence. Generally called because of a
......@@ -458,7 +531,7 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
int (*seq_exch_abort)(const struct fc_seq *req_sp,
int (*seq_exch_abort)(const struct fc_seq *,
unsigned int timer_msec);
/*
......@@ -467,14 +540,14 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
void (*exch_done)(struct fc_seq *sp);
void (*exch_done)(struct fc_seq *);
/*
* Start a new sequence on the same exchange/sequence tuple.
*
* STATUS: OPTIONAL
*/
struct fc_seq *(*seq_start_next)(struct fc_seq *sp);
struct fc_seq *(*seq_start_next)(struct fc_seq *);
/*
* Reset an exchange manager, completing all sequences and exchanges.
......@@ -483,8 +556,7 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
void (*exch_mgr_reset)(struct fc_lport *,
u32 s_id, u32 d_id);
void (*exch_mgr_reset)(struct fc_lport *, u32 s_id, u32 d_id);
/*
* Flush the rport work queue. Generally used before shutdown.
......@@ -498,8 +570,8 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
void (*lport_recv)(struct fc_lport *lp, struct fc_seq *sp,
struct fc_frame *fp);
void (*lport_recv)(struct fc_lport *, struct fc_seq *,
struct fc_frame *);
/*
* Reset the local port.
......@@ -565,31 +637,31 @@ struct libfc_function_template {
*
* STATUS: OPTIONAL
*/
int (*fcp_cmd_send)(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
void (*resp)(struct fc_seq *, struct fc_frame *fp,
void *arg));
int (*fcp_cmd_send)(struct fc_lport *, struct fc_fcp_pkt *,
void (*resp)(struct fc_seq *, struct fc_frame *,
void *));
/*
* Cleanup the FCP layer, used durring link down and reset
*
* STATUS: OPTIONAL
*/
void (*fcp_cleanup)(struct fc_lport *lp);
void (*fcp_cleanup)(struct fc_lport *);
/*
* Abort all I/O on a local port
*
* STATUS: OPTIONAL
*/
void (*fcp_abort_io)(struct fc_lport *lp);
void (*fcp_abort_io)(struct fc_lport *);
/*
* Receive a request for the discovery layer.
*
* STATUS: OPTIONAL
*/
void (*disc_recv_req)(struct fc_seq *,
struct fc_frame *, struct fc_lport *);
void (*disc_recv_req)(struct fc_seq *, struct fc_frame *,
struct fc_lport *);
/*
* Start discovery for a local port.
......@@ -618,7 +690,22 @@ struct libfc_function_template {
void (*disc_stop_final) (struct fc_lport *);
};
/* information used by the discovery layer */
/**
* struct fc_disc - Discovery context
* @retry_count: Number of retries
* @pending: 1 if discovery is pending, 0 if not
* @requesting: 1 if discovery has been requested, 0 if not
* @seq_count: Number of sequences used for discovery
* @buf_len: Length of the discovery buffer
* @disc_id: Discovery ID
* @rports: List of discovered remote ports
* @lport: The local port that discovery is for
* @disc_mutex: Mutex that protects the discovery context
* @partial_buf: Partial name buffer (if names are returned
* in multiple frames)
* @disc_work: handle for delayed work context
* @disc_callback: Callback routine called when discovery completes
*/
struct fc_disc {
unsigned char retry_count;
unsigned char pending;
......@@ -627,124 +714,200 @@ struct fc_disc {
unsigned char buf_len;
u16 disc_id;
void (*disc_callback)(struct fc_lport *,
enum fc_disc_event);
struct list_head rports;
struct fc_lport *lport;
struct mutex disc_mutex;
struct fc_gpn_ft_resp partial_buf; /* partial name buffer */
struct fc_gpn_ft_resp partial_buf;
struct delayed_work disc_work;
void (*disc_callback)(struct fc_lport *,
enum fc_disc_event);
};
/**
* struct fc_lport - Local port
* @host: The SCSI host associated with a local port
* @ema_list: Exchange manager anchor list
* @dns_rdata: The directory server remote port
* @ptp_rdata: Point to point remote port
* @scsi_priv: FCP layer internal data
* @disc: Discovery context
* @vports: Child vports if N_Port
* @vport: Parent vport if VN_Port
* @tt: Libfc function template
* @link_up: Link state (1 = link up, 0 = link down)
* @qfull: Queue state (1 queue is full, 0 queue is not full)
* @state: Identifies the state
* @boot_time: Timestamp indicating when the local port came online
* @host_stats: SCSI host statistics
* @dev_stats: FCoE device stats (TODO: libfc should not be
* FCoE aware)
* @retry_count: Number of retries in the current state
* @wwpn: World Wide Port Name
* @wwnn: World Wide Node Name
* @service_params: Common service parameters
* @e_d_tov: Error detection timeout value
* @r_a_tov: Resouce allocation timeout value
* @rnid_gen: RNID information
* @sg_supp: Indicates if scatter gather is supported
* @seq_offload: Indicates if sequence offload is supported
* @crc_offload: Indicates if CRC offload is supported
* @lro_enabled: Indicates if large receive offload is supported
* @does_npiv: Supports multiple vports
* @npiv_enabled: Switch/fabric allows NPIV
* @mfs: The maximum Fibre Channel payload size
* @max_retry_count: The maximum retry attempts
* @max_rport_retry_count: The maximum remote port retry attempts
* @lro_xid: The maximum XID for LRO
* @lso_max: The maximum large offload send size
* @fcts: FC-4 type mask
* @lp_mutex: Mutex to protect the local port
* @list: Handle for list of local ports
* @retry_work: Handle to local port for delayed retry context
*/
struct fc_lport {
struct list_head list;
/* Associations */
struct Scsi_Host *host;
struct list_head ema_list;
struct list_head vports; /* child vports if N_Port */
struct fc_vport *vport; /* parent vport if VN_Port */
struct fc_rport_priv *dns_rp;
struct fc_rport_priv *ptp_rp;
struct fc_rport_priv *dns_rdata;
struct fc_rport_priv *ptp_rdata;
void *scsi_priv;
struct fc_disc disc;
/* Virtual port information */
struct list_head vports;
struct fc_vport *vport;
/* Operational Information */
struct libfc_function_template tt;
u8 link_up;
u8 qfull;
enum fc_lport_state state;
unsigned long boot_time;
struct fc_host_statistics host_stats;
struct fcoe_dev_stats *dev_stats;
u8 retry_count;
/* Fabric information */
u64 wwpn;
u64 wwnn;
u8 retry_count;
/* Capabilities */
u32 sg_supp:1; /* scatter gather supported */
u32 seq_offload:1; /* seq offload supported */
u32 crc_offload:1; /* crc offload supported */
u32 lro_enabled:1; /* large receive offload */
u32 does_npiv:1; /* supports multiple vports */
u32 npiv_enabled:1; /* switch/fabric allows NPIV */
u32 mfs; /* max FC payload size */
unsigned int service_params;
unsigned int e_d_tov;
unsigned int r_a_tov;
struct fc_els_rnid_gen rnid_gen;
/* Capabilities */
u32 sg_supp:1;
u32 seq_offload:1;
u32 crc_offload:1;
u32 lro_enabled:1;
u32 does_npiv:1;
u32 npiv_enabled:1;
u32 mfs;
u8 max_retry_count;
u8 max_rport_retry_count;
u16 link_speed;
u16 link_supported_speeds;
u16 lro_xid; /* max xid for fcoe lro */
unsigned int lso_max; /* max large send size */
struct fc_ns_fts fcts; /* FC-4 type masks */
struct fc_els_rnid_gen rnid_gen; /* RNID information */
/* Semaphores */
struct mutex lp_mutex;
u16 lro_xid;
unsigned int lso_max;
struct fc_ns_fts fcts;
/* Miscellaneous */
struct mutex lp_mutex;
struct list_head list;
struct delayed_work retry_work;
};
/*
* FC_LPORT HELPER FUNCTIONS
*****************************/
static inline int fc_lport_test_ready(struct fc_lport *lp)
/**
* fc_lport_test_ready() - Determine if a local port is in the READY state
* @lport: The local port to test
*/
static inline int fc_lport_test_ready(struct fc_lport *lport)
{
return lp->state == LPORT_ST_READY;
return lport->state == LPORT_ST_READY;
}
static inline void fc_set_wwnn(struct fc_lport *lp, u64 wwnn)
/**
* fc_set_wwnn() - Set the World Wide Node Name of a local port
* @lport: The local port whose WWNN is to be set
* @wwnn: The new WWNN
*/
static inline void fc_set_wwnn(struct fc_lport *lport, u64 wwnn)
{
lp->wwnn = wwnn;
lport->wwnn = wwnn;
}
static inline void fc_set_wwpn(struct fc_lport *lp, u64 wwnn)
/**
* fc_set_wwpn() - Set the World Wide Port Name of a local port
* @lport: The local port whose WWPN is to be set
* @wwnn: The new WWPN
*/
static inline void fc_set_wwpn(struct fc_lport *lport, u64 wwnn)
{
lp->wwpn = wwnn;
lport->wwpn = wwnn;
}
static inline void fc_lport_state_enter(struct fc_lport *lp,
/**
* fc_lport_state_enter() - Change a local port's state
* @lport: The local port whose state is to change
* @state: The new state
*/
static inline void fc_lport_state_enter(struct fc_lport *lport,
enum fc_lport_state state)
{
if (state != lp->state)
lp->retry_count = 0;
lp->state = state;
if (state != lport->state)
lport->retry_count = 0;
lport->state = state;
}
static inline int fc_lport_init_stats(struct fc_lport *lp)
/**
* fc_lport_init_stats() - Allocate per-CPU statistics for a local port
* @lport: The local port whose statistics are to be initialized
*/
static inline int fc_lport_init_stats(struct fc_lport *lport)
{
/* allocate per cpu stats block */
lp->dev_stats = alloc_percpu(struct fcoe_dev_stats);
if (!lp->dev_stats)
lport->dev_stats = alloc_percpu(struct fcoe_dev_stats);
if (!lport->dev_stats)
return -ENOMEM;
return 0;
}
static inline void fc_lport_free_stats(struct fc_lport *lp)
/**
* fc_lport_free_stats() - Free memory for a local port's statistics
* @lport: The local port whose statistics are to be freed
*/
static inline void fc_lport_free_stats(struct fc_lport *lport)
{
free_percpu(lp->dev_stats);
free_percpu(lport->dev_stats);
}
static inline struct fcoe_dev_stats *fc_lport_get_stats(struct fc_lport *lp)
/**
* fc_lport_get_stats() - Get a local port's statistics
* @lport: The local port whose statistics are to be retreived
*/
static inline struct fcoe_dev_stats *fc_lport_get_stats(struct fc_lport *lport)
{
return per_cpu_ptr(lp->dev_stats, smp_processor_id());
return per_cpu_ptr(lport->dev_stats, smp_processor_id());
}
static inline void *lport_priv(const struct fc_lport *lp)
/**
* lport_priv() - Return the private data from a local port
* @lport: The local port whose private data is to be retreived
*/
static inline void *lport_priv(const struct fc_lport *lport)
{
return (void *)(lp + 1);
return (void *)(lport + 1);
}
/**
* libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport
* @sht: ptr to the scsi host templ
* @priv_size: size of private data after fc_lport
* libfc_host_alloc() - Allocate a Scsi_Host with room for a local port and
* LLD private data
* @sht: The SCSI host template
* @priv_size: Size of private data
*
* Returns: libfc lport
*/
......@@ -765,156 +928,73 @@ libfc_host_alloc(struct scsi_host_template *sht, int priv_size)
}
/*
* LOCAL PORT LAYER
* FC_FCP HELPER FUNCTIONS
*****************************/
int fc_lport_init(struct fc_lport *lp);
/*
* Destroy the specified local port by finding and freeing all
* fc_rports associated with it and then by freeing the fc_lport
* itself.
*/
int fc_lport_destroy(struct fc_lport *lp);
/*
* Logout the specified local port from the fabric
*/
int fc_fabric_logoff(struct fc_lport *lp);
/*
* Initiate the LP state machine. This handler will use fc_host_attr
* to store the FLOGI service parameters, so fc_host_attr must be
* initialized before calling this handler.
*/
int fc_fabric_login(struct fc_lport *lp);
static inline bool fc_fcp_is_read(const struct fc_fcp_pkt *fsp)
{
if (fsp && fsp->cmd)
return fsp->cmd->sc_data_direction == DMA_FROM_DEVICE;
return false;
}
/*
* The link is up for the given local port.
*/
* LOCAL PORT LAYER
*****************************/
int fc_lport_init(struct fc_lport *);
int fc_lport_destroy(struct fc_lport *);
int fc_fabric_logoff(struct fc_lport *);
int fc_fabric_login(struct fc_lport *);
void __fc_linkup(struct fc_lport *);
void fc_linkup(struct fc_lport *);
/*
* Link is down for the given local port.
*/
void __fc_linkdown(struct fc_lport *);
void fc_linkdown(struct fc_lport *);
/*
* Configure the local port.
*/
void fc_vport_setlink(struct fc_lport *);
void fc_vports_linkchange(struct fc_lport *);
int fc_lport_config(struct fc_lport *);
/*
* Reset the local port.
*/
int fc_lport_reset(struct fc_lport *);
/*
* Set the mfs or reset
*/
int fc_set_mfs(struct fc_lport *lp, u32 mfs);
/*
* Allocate a new lport struct for an NPIV VN_Port
*/
struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize);
/*
* Find an NPIV VN_Port by port ID
*/
struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id);
/*
* NPIV VN_Port link state management
*/
void fc_vport_setlink(struct fc_lport *vn_port);
void fc_vports_linkchange(struct fc_lport *n_port);
/*
* Issue fc pass-thru request via bsg interface
*/
int fc_lport_bsg_request(struct fc_bsg_job *job);
int fc_set_mfs(struct fc_lport *, u32 mfs);
struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize);
struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id);
int fc_lport_bsg_request(struct fc_bsg_job *);
/*
* REMOTE PORT LAYER
*****************************/
int fc_rport_init(struct fc_lport *lp);
void fc_rport_terminate_io(struct fc_rport *rp);
int fc_rport_init(struct fc_lport *);
void fc_rport_terminate_io(struct fc_rport *);
/*
* DISCOVERY LAYER
*****************************/
int fc_disc_init(struct fc_lport *lp);
int fc_disc_init(struct fc_lport *);
/*
* SCSI LAYER
* FCP LAYER
*****************************/
/*
* Initialize the SCSI block of libfc
*/
int fc_fcp_init(struct fc_lport *);
void fc_fcp_destroy(struct fc_lport *);
/*
* This section provides an API which allows direct interaction
* with the SCSI-ml. Each of these functions satisfies a function
* pointer defined in Scsi_Host and therefore is always called
* directly from the SCSI-ml.
*/
int fc_queuecommand(struct scsi_cmnd *sc_cmd,
* SCSI INTERACTION LAYER
*****************************/
int fc_queuecommand(struct scsi_cmnd *,
void (*done)(struct scsi_cmnd *));
/*
* Send an ABTS frame to the target device. The sc_cmd argument
* is a pointer to the SCSI command to be aborted.
*/
int fc_eh_abort(struct scsi_cmnd *sc_cmd);
/*
* Reset a LUN by sending send the tm cmd to the target.
*/
int fc_eh_device_reset(struct scsi_cmnd *sc_cmd);
/*
* Reset the host adapter.
*/
int fc_eh_host_reset(struct scsi_cmnd *sc_cmd);
/*
* Check rport status.
*/
int fc_slave_alloc(struct scsi_device *sdev);
/*
* Adjust the queue depth.
*/
int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason);
/*
* Change the tag type.
*/
int fc_change_queue_type(struct scsi_device *sdev, int tag_type);
/*
* Free memory pools used by the FCP layer.
*/
void fc_fcp_destroy(struct fc_lport *);
int fc_eh_abort(struct scsi_cmnd *);
int fc_eh_device_reset(struct scsi_cmnd *);
int fc_eh_host_reset(struct scsi_cmnd *);
int fc_slave_alloc(struct scsi_device *);
int fc_change_queue_depth(struct scsi_device *, int qdepth, int reason);
int fc_change_queue_type(struct scsi_device *, int tag_type);
/*
* ELS/CT interface
*****************************/
/*
* Initializes ELS/CT interface
*/
int fc_elsct_init(struct fc_lport *lp);
struct fc_seq *fc_elsct_send(struct fc_lport *lport,
u32 did,
struct fc_frame *fp,
int fc_elsct_init(struct fc_lport *);
struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did,
struct fc_frame *,
unsigned int op,
void (*resp)(struct fc_seq *,
struct fc_frame *fp,
struct fc_frame *,
void *arg),
void *arg, u32 timer_msec);
void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *);
......@@ -924,90 +1004,26 @@ void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *);
/*
* EXCHANGE MANAGER LAYER
*****************************/
/*
* Initializes Exchange Manager related
* function pointers in struct libfc_function_template.
*/
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,
int fc_exch_init(struct fc_lport *);
struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *,
struct fc_exch_mgr *,
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);
/*
* Clone an exchange manager list, getting reference holds for each EM.
* This is for use with NPIV and sharing the X_ID space between VN_Ports.
*/
void fc_exch_mgr_del(struct fc_exch_mgr_anchor *);
int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst);
/*
* Allocates an Exchange Manager (EM).
*
* The EM manages exchanges for their allocation and
* free, also allows exchange lookup for received
* frame.
*
* The class is used for initializing FC class of
* allocated exchange from EM.
*
* The min_xid and max_xid will limit new
* exchange ID (XID) within this range for
* a new exchange.
* The LLD may choose to have multiple EMs,
* e.g. one EM instance per CPU receive thread in LLD.
*
* 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,
struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *, enum fc_class class,
u16 min_xid, u16 max_xid,
bool (*match)(struct fc_frame *));
/*
* Free all exchange managers of a lport.
*/
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_frame *fp);
/*
* 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_free(struct fc_lport *);
void fc_exch_recv(struct fc_lport *, struct fc_frame *);
void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id);
/*
* Functions for fc_functions_template
*/
void fc_get_host_speed(struct Scsi_Host *shost);
void fc_get_host_port_type(struct Scsi_Host *shost);
void fc_get_host_port_state(struct Scsi_Host *shost);
void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout);
void fc_get_host_speed(struct Scsi_Host *);
void fc_get_host_port_type(struct Scsi_Host *);
void fc_get_host_port_state(struct Scsi_Host *);
void fc_set_rport_loss_tmo(struct fc_rport *, u32 timeout);
struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *);
#endif /* _LIBFC_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment