xref: /linux/drivers/scsi/libfc/fc_exch.c (revision 42e9a92fe6a9095bd68a379aaec7ad2be0337f7a)
1*42e9a92fSRobert Love /*
2*42e9a92fSRobert Love  * Copyright(c) 2007 Intel Corporation. All rights reserved.
3*42e9a92fSRobert Love  * Copyright(c) 2008 Red Hat, Inc.  All rights reserved.
4*42e9a92fSRobert Love  * Copyright(c) 2008 Mike Christie
5*42e9a92fSRobert Love  *
6*42e9a92fSRobert Love  * This program is free software; you can redistribute it and/or modify it
7*42e9a92fSRobert Love  * under the terms and conditions of the GNU General Public License,
8*42e9a92fSRobert Love  * version 2, as published by the Free Software Foundation.
9*42e9a92fSRobert Love  *
10*42e9a92fSRobert Love  * This program is distributed in the hope it will be useful, but WITHOUT
11*42e9a92fSRobert Love  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12*42e9a92fSRobert Love  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13*42e9a92fSRobert Love  * more details.
14*42e9a92fSRobert Love  *
15*42e9a92fSRobert Love  * You should have received a copy of the GNU General Public License along with
16*42e9a92fSRobert Love  * this program; if not, write to the Free Software Foundation, Inc.,
17*42e9a92fSRobert Love  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18*42e9a92fSRobert Love  *
19*42e9a92fSRobert Love  * Maintained at www.Open-FCoE.org
20*42e9a92fSRobert Love  */
21*42e9a92fSRobert Love 
22*42e9a92fSRobert Love /*
23*42e9a92fSRobert Love  * Fibre Channel exchange and sequence handling.
24*42e9a92fSRobert Love  */
25*42e9a92fSRobert Love 
26*42e9a92fSRobert Love #include <linux/timer.h>
27*42e9a92fSRobert Love #include <linux/gfp.h>
28*42e9a92fSRobert Love #include <linux/err.h>
29*42e9a92fSRobert Love 
30*42e9a92fSRobert Love #include <scsi/fc/fc_fc2.h>
31*42e9a92fSRobert Love 
32*42e9a92fSRobert Love #include <scsi/libfc.h>
33*42e9a92fSRobert Love #include <scsi/fc_encode.h>
34*42e9a92fSRobert Love 
35*42e9a92fSRobert Love #define	  FC_DEF_R_A_TOV      (10 * 1000) /* resource allocation timeout */
36*42e9a92fSRobert Love 
37*42e9a92fSRobert Love /*
38*42e9a92fSRobert Love  * fc_exch_debug can be set in debugger or at compile time to get more logs.
39*42e9a92fSRobert Love  */
40*42e9a92fSRobert Love static int fc_exch_debug;
41*42e9a92fSRobert Love 
42*42e9a92fSRobert Love #define FC_DEBUG_EXCH(fmt...)			\
43*42e9a92fSRobert Love 	do {					\
44*42e9a92fSRobert Love 		if (fc_exch_debug)		\
45*42e9a92fSRobert Love 			FC_DBG(fmt);		\
46*42e9a92fSRobert Love 	} while (0)
47*42e9a92fSRobert Love 
48*42e9a92fSRobert Love static struct kmem_cache *fc_em_cachep;	/* cache for exchanges */
49*42e9a92fSRobert Love 
50*42e9a92fSRobert Love /*
51*42e9a92fSRobert Love  * Structure and function definitions for managing Fibre Channel Exchanges
52*42e9a92fSRobert Love  * and Sequences.
53*42e9a92fSRobert Love  *
54*42e9a92fSRobert Love  * The three primary structures used here are fc_exch_mgr, fc_exch, and fc_seq.
55*42e9a92fSRobert Love  *
56*42e9a92fSRobert Love  * fc_exch_mgr holds the exchange state for an N port
57*42e9a92fSRobert Love  *
58*42e9a92fSRobert Love  * fc_exch holds state for one exchange and links to its active sequence.
59*42e9a92fSRobert Love  *
60*42e9a92fSRobert Love  * fc_seq holds the state for an individual sequence.
61*42e9a92fSRobert Love  */
62*42e9a92fSRobert Love 
63*42e9a92fSRobert Love /*
64*42e9a92fSRobert Love  * Exchange manager.
65*42e9a92fSRobert Love  *
66*42e9a92fSRobert Love  * This structure is the center for creating exchanges and sequences.
67*42e9a92fSRobert Love  * It manages the allocation of exchange IDs.
68*42e9a92fSRobert Love  */
69*42e9a92fSRobert Love struct fc_exch_mgr {
70*42e9a92fSRobert Love 	enum fc_class	class;		/* default class for sequences */
71*42e9a92fSRobert Love 	spinlock_t	em_lock;	/* exchange manager lock,
72*42e9a92fSRobert Love 					   must be taken before ex_lock */
73*42e9a92fSRobert Love 	u16		last_xid;	/* last allocated exchange ID */
74*42e9a92fSRobert Love 	u16		min_xid;	/* min exchange ID */
75*42e9a92fSRobert Love 	u16		max_xid;	/* max exchange ID */
76*42e9a92fSRobert Love 	u16		max_read;	/* max exchange ID for read */
77*42e9a92fSRobert Love 	u16		last_read;	/* last xid allocated for read */
78*42e9a92fSRobert Love 	u32	total_exches;		/* total allocated exchanges */
79*42e9a92fSRobert Love 	struct list_head	ex_list;	/* allocated exchanges list */
80*42e9a92fSRobert Love 	struct fc_lport	*lp;		/* fc device instance */
81*42e9a92fSRobert Love 	mempool_t	*ep_pool;	/* reserve ep's */
82*42e9a92fSRobert Love 
83*42e9a92fSRobert Love 	/*
84*42e9a92fSRobert Love 	 * currently exchange mgr stats are updated but not used.
85*42e9a92fSRobert Love 	 * either stats can be expose via sysfs or remove them
86*42e9a92fSRobert Love 	 * all together if not used XXX
87*42e9a92fSRobert Love 	 */
88*42e9a92fSRobert Love 	struct {
89*42e9a92fSRobert Love 		atomic_t no_free_exch;
90*42e9a92fSRobert Love 		atomic_t no_free_exch_xid;
91*42e9a92fSRobert Love 		atomic_t xid_not_found;
92*42e9a92fSRobert Love 		atomic_t xid_busy;
93*42e9a92fSRobert Love 		atomic_t seq_not_found;
94*42e9a92fSRobert Love 		atomic_t non_bls_resp;
95*42e9a92fSRobert Love 	} stats;
96*42e9a92fSRobert Love 	struct fc_exch **exches;	/* for exch pointers indexed by xid */
97*42e9a92fSRobert Love };
98*42e9a92fSRobert Love #define	fc_seq_exch(sp) container_of(sp, struct fc_exch, seq)
99*42e9a92fSRobert Love 
100*42e9a92fSRobert Love static void fc_exch_rrq(struct fc_exch *);
101*42e9a92fSRobert Love static void fc_seq_ls_acc(struct fc_seq *);
102*42e9a92fSRobert Love static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason,
103*42e9a92fSRobert Love 			  enum fc_els_rjt_explan);
104*42e9a92fSRobert Love static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *);
105*42e9a92fSRobert Love static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *);
106*42e9a92fSRobert Love static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp);
107*42e9a92fSRobert Love 
108*42e9a92fSRobert Love /*
109*42e9a92fSRobert Love  * Internal implementation notes.
110*42e9a92fSRobert Love  *
111*42e9a92fSRobert Love  * The exchange manager is one by default in libfc but LLD may choose
112*42e9a92fSRobert Love  * to have one per CPU. The sequence manager is one per exchange manager
113*42e9a92fSRobert Love  * and currently never separated.
114*42e9a92fSRobert Love  *
115*42e9a92fSRobert Love  * Section 9.8 in FC-FS-2 specifies:  "The SEQ_ID is a one-byte field
116*42e9a92fSRobert Love  * assigned by the Sequence Initiator that shall be unique for a specific
117*42e9a92fSRobert Love  * D_ID and S_ID pair while the Sequence is open."   Note that it isn't
118*42e9a92fSRobert Love  * qualified by exchange ID, which one might think it would be.
119*42e9a92fSRobert Love  * In practice this limits the number of open sequences and exchanges to 256
120*42e9a92fSRobert Love  * per session.	 For most targets we could treat this limit as per exchange.
121*42e9a92fSRobert Love  *
122*42e9a92fSRobert Love  * The exchange and its sequence are freed when the last sequence is received.
123*42e9a92fSRobert Love  * It's possible for the remote port to leave an exchange open without
124*42e9a92fSRobert Love  * sending any sequences.
125*42e9a92fSRobert Love  *
126*42e9a92fSRobert Love  * Notes on reference counts:
127*42e9a92fSRobert Love  *
128*42e9a92fSRobert Love  * Exchanges are reference counted and exchange gets freed when the reference
129*42e9a92fSRobert Love  * count becomes zero.
130*42e9a92fSRobert Love  *
131*42e9a92fSRobert Love  * Timeouts:
132*42e9a92fSRobert Love  * Sequences are timed out for E_D_TOV and R_A_TOV.
133*42e9a92fSRobert Love  *
134*42e9a92fSRobert Love  * Sequence event handling:
135*42e9a92fSRobert Love  *
136*42e9a92fSRobert Love  * The following events may occur on initiator sequences:
137*42e9a92fSRobert Love  *
138*42e9a92fSRobert Love  *	Send.
139*42e9a92fSRobert Love  *	    For now, the whole thing is sent.
140*42e9a92fSRobert Love  *	Receive ACK
141*42e9a92fSRobert Love  *	    This applies only to class F.
142*42e9a92fSRobert Love  *	    The sequence is marked complete.
143*42e9a92fSRobert Love  *	ULP completion.
144*42e9a92fSRobert Love  *	    The upper layer calls fc_exch_done() when done
145*42e9a92fSRobert Love  *	    with exchange and sequence tuple.
146*42e9a92fSRobert Love  *	RX-inferred completion.
147*42e9a92fSRobert Love  *	    When we receive the next sequence on the same exchange, we can
148*42e9a92fSRobert Love  *	    retire the previous sequence ID.  (XXX not implemented).
149*42e9a92fSRobert Love  *	Timeout.
150*42e9a92fSRobert Love  *	    R_A_TOV frees the sequence ID.  If we're waiting for ACK,
151*42e9a92fSRobert Love  *	    E_D_TOV causes abort and calls upper layer response handler
152*42e9a92fSRobert Love  *	    with FC_EX_TIMEOUT error.
153*42e9a92fSRobert Love  *	Receive RJT
154*42e9a92fSRobert Love  *	    XXX defer.
155*42e9a92fSRobert Love  *	Send ABTS
156*42e9a92fSRobert Love  *	    On timeout.
157*42e9a92fSRobert Love  *
158*42e9a92fSRobert Love  * The following events may occur on recipient sequences:
159*42e9a92fSRobert Love  *
160*42e9a92fSRobert Love  *	Receive
161*42e9a92fSRobert Love  *	    Allocate sequence for first frame received.
162*42e9a92fSRobert Love  *	    Hold during receive handler.
163*42e9a92fSRobert Love  *	    Release when final frame received.
164*42e9a92fSRobert Love  *	    Keep status of last N of these for the ELS RES command.  XXX TBD.
165*42e9a92fSRobert Love  *	Receive ABTS
166*42e9a92fSRobert Love  *	    Deallocate sequence
167*42e9a92fSRobert Love  *	Send RJT
168*42e9a92fSRobert Love  *	    Deallocate
169*42e9a92fSRobert Love  *
170*42e9a92fSRobert Love  * For now, we neglect conditions where only part of a sequence was
171*42e9a92fSRobert Love  * received or transmitted, or where out-of-order receipt is detected.
172*42e9a92fSRobert Love  */
173*42e9a92fSRobert Love 
174*42e9a92fSRobert Love /*
175*42e9a92fSRobert Love  * Locking notes:
176*42e9a92fSRobert Love  *
177*42e9a92fSRobert Love  * The EM code run in a per-CPU worker thread.
178*42e9a92fSRobert Love  *
179*42e9a92fSRobert Love  * To protect against concurrency between a worker thread code and timers,
180*42e9a92fSRobert Love  * sequence allocation and deallocation must be locked.
181*42e9a92fSRobert Love  *  - exchange refcnt can be done atomicly without locks.
182*42e9a92fSRobert Love  *  - sequence allocation must be locked by exch lock.
183*42e9a92fSRobert Love  *  - If the em_lock and ex_lock must be taken at the same time, then the
184*42e9a92fSRobert Love  *    em_lock must be taken before the ex_lock.
185*42e9a92fSRobert Love  */
186*42e9a92fSRobert Love 
187*42e9a92fSRobert Love /*
188*42e9a92fSRobert Love  * opcode names for debugging.
189*42e9a92fSRobert Love  */
190*42e9a92fSRobert Love static char *fc_exch_rctl_names[] = FC_RCTL_NAMES_INIT;
191*42e9a92fSRobert Love 
192*42e9a92fSRobert Love #define FC_TABLE_SIZE(x)   (sizeof(x) / sizeof(x[0]))
193*42e9a92fSRobert Love 
194*42e9a92fSRobert Love static inline const char *fc_exch_name_lookup(unsigned int op, char **table,
195*42e9a92fSRobert Love 					      unsigned int max_index)
196*42e9a92fSRobert Love {
197*42e9a92fSRobert Love 	const char *name = NULL;
198*42e9a92fSRobert Love 
199*42e9a92fSRobert Love 	if (op < max_index)
200*42e9a92fSRobert Love 		name = table[op];
201*42e9a92fSRobert Love 	if (!name)
202*42e9a92fSRobert Love 		name = "unknown";
203*42e9a92fSRobert Love 	return name;
204*42e9a92fSRobert Love }
205*42e9a92fSRobert Love 
206*42e9a92fSRobert Love static const char *fc_exch_rctl_name(unsigned int op)
207*42e9a92fSRobert Love {
208*42e9a92fSRobert Love 	return fc_exch_name_lookup(op, fc_exch_rctl_names,
209*42e9a92fSRobert Love 				   FC_TABLE_SIZE(fc_exch_rctl_names));
210*42e9a92fSRobert Love }
211*42e9a92fSRobert Love 
212*42e9a92fSRobert Love /*
213*42e9a92fSRobert Love  * Hold an exchange - keep it from being freed.
214*42e9a92fSRobert Love  */
215*42e9a92fSRobert Love static void fc_exch_hold(struct fc_exch *ep)
216*42e9a92fSRobert Love {
217*42e9a92fSRobert Love 	atomic_inc(&ep->ex_refcnt);
218*42e9a92fSRobert Love }
219*42e9a92fSRobert Love 
220*42e9a92fSRobert Love /*
221*42e9a92fSRobert Love  * setup fc hdr by initializing few more FC header fields and sof/eof.
222*42e9a92fSRobert Love  * Initialized fields by this func:
223*42e9a92fSRobert Love  *	- fh_ox_id, fh_rx_id, fh_seq_id, fh_seq_cnt
224*42e9a92fSRobert Love  *	- sof and eof
225*42e9a92fSRobert Love  */
226*42e9a92fSRobert Love static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp,
227*42e9a92fSRobert Love 			      u32 f_ctl)
228*42e9a92fSRobert Love {
229*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
230*42e9a92fSRobert Love 	u16 fill;
231*42e9a92fSRobert Love 
232*42e9a92fSRobert Love 	fr_sof(fp) = ep->class;
233*42e9a92fSRobert Love 	if (ep->seq.cnt)
234*42e9a92fSRobert Love 		fr_sof(fp) = fc_sof_normal(ep->class);
235*42e9a92fSRobert Love 
236*42e9a92fSRobert Love 	if (f_ctl & FC_FC_END_SEQ) {
237*42e9a92fSRobert Love 		fr_eof(fp) = FC_EOF_T;
238*42e9a92fSRobert Love 		if (fc_sof_needs_ack(ep->class))
239*42e9a92fSRobert Love 			fr_eof(fp) = FC_EOF_N;
240*42e9a92fSRobert Love 		/*
241*42e9a92fSRobert Love 		 * Form f_ctl.
242*42e9a92fSRobert Love 		 * The number of fill bytes to make the length a 4-byte
243*42e9a92fSRobert Love 		 * multiple is the low order 2-bits of the f_ctl.
244*42e9a92fSRobert Love 		 * The fill itself will have been cleared by the frame
245*42e9a92fSRobert Love 		 * allocation.
246*42e9a92fSRobert Love 		 * After this, the length will be even, as expected by
247*42e9a92fSRobert Love 		 * the transport.
248*42e9a92fSRobert Love 		 */
249*42e9a92fSRobert Love 		fill = fr_len(fp) & 3;
250*42e9a92fSRobert Love 		if (fill) {
251*42e9a92fSRobert Love 			fill = 4 - fill;
252*42e9a92fSRobert Love 			/* TODO, this may be a problem with fragmented skb */
253*42e9a92fSRobert Love 			skb_put(fp_skb(fp), fill);
254*42e9a92fSRobert Love 			hton24(fh->fh_f_ctl, f_ctl | fill);
255*42e9a92fSRobert Love 		}
256*42e9a92fSRobert Love 	} else {
257*42e9a92fSRobert Love 		WARN_ON(fr_len(fp) % 4 != 0);	/* no pad to non last frame */
258*42e9a92fSRobert Love 		fr_eof(fp) = FC_EOF_N;
259*42e9a92fSRobert Love 	}
260*42e9a92fSRobert Love 
261*42e9a92fSRobert Love 	/*
262*42e9a92fSRobert Love 	 * Initialize remainig fh fields
263*42e9a92fSRobert Love 	 * from fc_fill_fc_hdr
264*42e9a92fSRobert Love 	 */
265*42e9a92fSRobert Love 	fh->fh_ox_id = htons(ep->oxid);
266*42e9a92fSRobert Love 	fh->fh_rx_id = htons(ep->rxid);
267*42e9a92fSRobert Love 	fh->fh_seq_id = ep->seq.id;
268*42e9a92fSRobert Love 	fh->fh_seq_cnt = htons(ep->seq.cnt);
269*42e9a92fSRobert Love }
270*42e9a92fSRobert Love 
271*42e9a92fSRobert Love 
272*42e9a92fSRobert Love /*
273*42e9a92fSRobert Love  * Release a reference to an exchange.
274*42e9a92fSRobert Love  * If the refcnt goes to zero and the exchange is complete, it is freed.
275*42e9a92fSRobert Love  */
276*42e9a92fSRobert Love static void fc_exch_release(struct fc_exch *ep)
277*42e9a92fSRobert Love {
278*42e9a92fSRobert Love 	struct fc_exch_mgr *mp;
279*42e9a92fSRobert Love 
280*42e9a92fSRobert Love 	if (atomic_dec_and_test(&ep->ex_refcnt)) {
281*42e9a92fSRobert Love 		mp = ep->em;
282*42e9a92fSRobert Love 		if (ep->destructor)
283*42e9a92fSRobert Love 			ep->destructor(&ep->seq, ep->arg);
284*42e9a92fSRobert Love 		if (ep->lp->tt.exch_put)
285*42e9a92fSRobert Love 			ep->lp->tt.exch_put(ep->lp, mp, ep->xid);
286*42e9a92fSRobert Love 		WARN_ON(!ep->esb_stat & ESB_ST_COMPLETE);
287*42e9a92fSRobert Love 		mempool_free(ep, mp->ep_pool);
288*42e9a92fSRobert Love 	}
289*42e9a92fSRobert Love }
290*42e9a92fSRobert Love 
291*42e9a92fSRobert Love static int fc_exch_done_locked(struct fc_exch *ep)
292*42e9a92fSRobert Love {
293*42e9a92fSRobert Love 	int rc = 1;
294*42e9a92fSRobert Love 
295*42e9a92fSRobert Love 	/*
296*42e9a92fSRobert Love 	 * We must check for completion in case there are two threads
297*42e9a92fSRobert Love 	 * tyring to complete this. But the rrq code will reuse the
298*42e9a92fSRobert Love 	 * ep, and in that case we only clear the resp and set it as
299*42e9a92fSRobert Love 	 * complete, so it can be reused by the timer to send the rrq.
300*42e9a92fSRobert Love 	 */
301*42e9a92fSRobert Love 	ep->resp = NULL;
302*42e9a92fSRobert Love 	if (ep->state & FC_EX_DONE)
303*42e9a92fSRobert Love 		return rc;
304*42e9a92fSRobert Love 	ep->esb_stat |= ESB_ST_COMPLETE;
305*42e9a92fSRobert Love 
306*42e9a92fSRobert Love 	if (!(ep->esb_stat & ESB_ST_REC_QUAL)) {
307*42e9a92fSRobert Love 		ep->state |= FC_EX_DONE;
308*42e9a92fSRobert Love 		if (cancel_delayed_work(&ep->timeout_work))
309*42e9a92fSRobert Love 			atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
310*42e9a92fSRobert Love 		rc = 0;
311*42e9a92fSRobert Love 	}
312*42e9a92fSRobert Love 	return rc;
313*42e9a92fSRobert Love }
314*42e9a92fSRobert Love 
315*42e9a92fSRobert Love static void fc_exch_mgr_delete_ep(struct fc_exch *ep)
316*42e9a92fSRobert Love {
317*42e9a92fSRobert Love 	struct fc_exch_mgr *mp;
318*42e9a92fSRobert Love 
319*42e9a92fSRobert Love 	mp = ep->em;
320*42e9a92fSRobert Love 	spin_lock_bh(&mp->em_lock);
321*42e9a92fSRobert Love 	WARN_ON(mp->total_exches <= 0);
322*42e9a92fSRobert Love 	mp->total_exches--;
323*42e9a92fSRobert Love 	mp->exches[ep->xid - mp->min_xid] = NULL;
324*42e9a92fSRobert Love 	list_del(&ep->ex_list);
325*42e9a92fSRobert Love 	spin_unlock_bh(&mp->em_lock);
326*42e9a92fSRobert Love 	fc_exch_release(ep);	/* drop hold for exch in mp */
327*42e9a92fSRobert Love }
328*42e9a92fSRobert Love 
329*42e9a92fSRobert Love /*
330*42e9a92fSRobert Love  * Internal version of fc_exch_timer_set - used with lock held.
331*42e9a92fSRobert Love  */
332*42e9a92fSRobert Love static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
333*42e9a92fSRobert Love 					    unsigned int timer_msec)
334*42e9a92fSRobert Love {
335*42e9a92fSRobert Love 	if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
336*42e9a92fSRobert Love 		return;
337*42e9a92fSRobert Love 
338*42e9a92fSRobert Love 	FC_DEBUG_EXCH("Exchange (%4x) timed out, notifying the upper layer\n",
339*42e9a92fSRobert Love 		      ep->xid);
340*42e9a92fSRobert Love 	if (schedule_delayed_work(&ep->timeout_work,
341*42e9a92fSRobert Love 				  msecs_to_jiffies(timer_msec)))
342*42e9a92fSRobert Love 		fc_exch_hold(ep);		/* hold for timer */
343*42e9a92fSRobert Love }
344*42e9a92fSRobert Love 
345*42e9a92fSRobert Love /*
346*42e9a92fSRobert Love  * Set timer for an exchange.
347*42e9a92fSRobert Love  * The time is a minimum delay in milliseconds until the timer fires.
348*42e9a92fSRobert Love  * Used for upper level protocols to time out the exchange.
349*42e9a92fSRobert Love  * The timer is cancelled when it fires or when the exchange completes.
350*42e9a92fSRobert Love  * Returns non-zero if a timer couldn't be allocated.
351*42e9a92fSRobert Love  */
352*42e9a92fSRobert Love static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec)
353*42e9a92fSRobert Love {
354*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
355*42e9a92fSRobert Love 	fc_exch_timer_set_locked(ep, timer_msec);
356*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
357*42e9a92fSRobert Love }
358*42e9a92fSRobert Love 
359*42e9a92fSRobert Love int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec)
360*42e9a92fSRobert Love {
361*42e9a92fSRobert Love 	struct fc_seq *sp;
362*42e9a92fSRobert Love 	struct fc_exch *ep;
363*42e9a92fSRobert Love 	struct fc_frame *fp;
364*42e9a92fSRobert Love 	int error;
365*42e9a92fSRobert Love 
366*42e9a92fSRobert Love 	ep = fc_seq_exch(req_sp);
367*42e9a92fSRobert Love 
368*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
369*42e9a92fSRobert Love 	if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) ||
370*42e9a92fSRobert Love 	    ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) {
371*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
372*42e9a92fSRobert Love 		return -ENXIO;
373*42e9a92fSRobert Love 	}
374*42e9a92fSRobert Love 
375*42e9a92fSRobert Love 	/*
376*42e9a92fSRobert Love 	 * Send the abort on a new sequence if possible.
377*42e9a92fSRobert Love 	 */
378*42e9a92fSRobert Love 	sp = fc_seq_start_next_locked(&ep->seq);
379*42e9a92fSRobert Love 	if (!sp) {
380*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
381*42e9a92fSRobert Love 		return -ENOMEM;
382*42e9a92fSRobert Love 	}
383*42e9a92fSRobert Love 
384*42e9a92fSRobert Love 	ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL;
385*42e9a92fSRobert Love 	if (timer_msec)
386*42e9a92fSRobert Love 		fc_exch_timer_set_locked(ep, timer_msec);
387*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
388*42e9a92fSRobert Love 
389*42e9a92fSRobert Love 	/*
390*42e9a92fSRobert Love 	 * If not logged into the fabric, don't send ABTS but leave
391*42e9a92fSRobert Love 	 * sequence active until next timeout.
392*42e9a92fSRobert Love 	 */
393*42e9a92fSRobert Love 	if (!ep->sid)
394*42e9a92fSRobert Love 		return 0;
395*42e9a92fSRobert Love 
396*42e9a92fSRobert Love 	/*
397*42e9a92fSRobert Love 	 * Send an abort for the sequence that timed out.
398*42e9a92fSRobert Love 	 */
399*42e9a92fSRobert Love 	fp = fc_frame_alloc(ep->lp, 0);
400*42e9a92fSRobert Love 	if (fp) {
401*42e9a92fSRobert Love 		fc_fill_fc_hdr(fp, FC_RCTL_BA_ABTS, ep->did, ep->sid,
402*42e9a92fSRobert Love 			       FC_TYPE_BLS, FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
403*42e9a92fSRobert Love 		error = fc_seq_send(ep->lp, sp, fp);
404*42e9a92fSRobert Love 	} else
405*42e9a92fSRobert Love 		error = -ENOBUFS;
406*42e9a92fSRobert Love 	return error;
407*42e9a92fSRobert Love }
408*42e9a92fSRobert Love EXPORT_SYMBOL(fc_seq_exch_abort);
409*42e9a92fSRobert Love 
410*42e9a92fSRobert Love /*
411*42e9a92fSRobert Love  * Exchange timeout - handle exchange timer expiration.
412*42e9a92fSRobert Love  * The timer will have been cancelled before this is called.
413*42e9a92fSRobert Love  */
414*42e9a92fSRobert Love static void fc_exch_timeout(struct work_struct *work)
415*42e9a92fSRobert Love {
416*42e9a92fSRobert Love 	struct fc_exch *ep = container_of(work, struct fc_exch,
417*42e9a92fSRobert Love 					  timeout_work.work);
418*42e9a92fSRobert Love 	struct fc_seq *sp = &ep->seq;
419*42e9a92fSRobert Love 	void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
420*42e9a92fSRobert Love 	void *arg;
421*42e9a92fSRobert Love 	u32 e_stat;
422*42e9a92fSRobert Love 	int rc = 1;
423*42e9a92fSRobert Love 
424*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
425*42e9a92fSRobert Love 	if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
426*42e9a92fSRobert Love 		goto unlock;
427*42e9a92fSRobert Love 
428*42e9a92fSRobert Love 	e_stat = ep->esb_stat;
429*42e9a92fSRobert Love 	if (e_stat & ESB_ST_COMPLETE) {
430*42e9a92fSRobert Love 		ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL;
431*42e9a92fSRobert Love 		if (e_stat & ESB_ST_REC_QUAL)
432*42e9a92fSRobert Love 			fc_exch_rrq(ep);
433*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
434*42e9a92fSRobert Love 		goto done;
435*42e9a92fSRobert Love 	} else {
436*42e9a92fSRobert Love 		resp = ep->resp;
437*42e9a92fSRobert Love 		arg = ep->arg;
438*42e9a92fSRobert Love 		ep->resp = NULL;
439*42e9a92fSRobert Love 		if (e_stat & ESB_ST_ABNORMAL)
440*42e9a92fSRobert Love 			rc = fc_exch_done_locked(ep);
441*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
442*42e9a92fSRobert Love 		if (!rc)
443*42e9a92fSRobert Love 			fc_exch_mgr_delete_ep(ep);
444*42e9a92fSRobert Love 		if (resp)
445*42e9a92fSRobert Love 			resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
446*42e9a92fSRobert Love 		fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
447*42e9a92fSRobert Love 		goto done;
448*42e9a92fSRobert Love 	}
449*42e9a92fSRobert Love unlock:
450*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
451*42e9a92fSRobert Love done:
452*42e9a92fSRobert Love 	/*
453*42e9a92fSRobert Love 	 * This release matches the hold taken when the timer was set.
454*42e9a92fSRobert Love 	 */
455*42e9a92fSRobert Love 	fc_exch_release(ep);
456*42e9a92fSRobert Love }
457*42e9a92fSRobert Love 
458*42e9a92fSRobert Love /*
459*42e9a92fSRobert Love  * Allocate a sequence.
460*42e9a92fSRobert Love  *
461*42e9a92fSRobert Love  * We don't support multiple originated sequences on the same exchange.
462*42e9a92fSRobert Love  * By implication, any previously originated sequence on this exchange
463*42e9a92fSRobert Love  * is complete, and we reallocate the same sequence.
464*42e9a92fSRobert Love  */
465*42e9a92fSRobert Love static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id)
466*42e9a92fSRobert Love {
467*42e9a92fSRobert Love 	struct fc_seq *sp;
468*42e9a92fSRobert Love 
469*42e9a92fSRobert Love 	sp = &ep->seq;
470*42e9a92fSRobert Love 	sp->ssb_stat = 0;
471*42e9a92fSRobert Love 	sp->cnt = 0;
472*42e9a92fSRobert Love 	sp->id = seq_id;
473*42e9a92fSRobert Love 	return sp;
474*42e9a92fSRobert Love }
475*42e9a92fSRobert Love 
476*42e9a92fSRobert Love /*
477*42e9a92fSRobert Love  * fc_em_alloc_xid - returns an xid based on request type
478*42e9a92fSRobert Love  * @lp : ptr to associated lport
479*42e9a92fSRobert Love  * @fp : ptr to the assocated frame
480*42e9a92fSRobert Love  *
481*42e9a92fSRobert Love  * check the associated fc_fsp_pkt to get scsi command type and
482*42e9a92fSRobert Love  * command direction to decide from which range this exch id
483*42e9a92fSRobert Love  * will be allocated from.
484*42e9a92fSRobert Love  *
485*42e9a92fSRobert Love  * Returns : 0 or an valid xid
486*42e9a92fSRobert Love  */
487*42e9a92fSRobert Love static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
488*42e9a92fSRobert Love {
489*42e9a92fSRobert Love 	u16 xid, min, max;
490*42e9a92fSRobert Love 	u16 *plast;
491*42e9a92fSRobert Love 	struct fc_exch *ep = NULL;
492*42e9a92fSRobert Love 
493*42e9a92fSRobert Love 	if (mp->max_read) {
494*42e9a92fSRobert Love 		if (fc_frame_is_read(fp)) {
495*42e9a92fSRobert Love 			min = mp->min_xid;
496*42e9a92fSRobert Love 			max = mp->max_read;
497*42e9a92fSRobert Love 			plast = &mp->last_read;
498*42e9a92fSRobert Love 		} else {
499*42e9a92fSRobert Love 			min = mp->max_read + 1;
500*42e9a92fSRobert Love 			max = mp->max_xid;
501*42e9a92fSRobert Love 			plast = &mp->last_xid;
502*42e9a92fSRobert Love 		}
503*42e9a92fSRobert Love 	} else {
504*42e9a92fSRobert Love 		min = mp->min_xid;
505*42e9a92fSRobert Love 		max = mp->max_xid;
506*42e9a92fSRobert Love 		plast = &mp->last_xid;
507*42e9a92fSRobert Love 	}
508*42e9a92fSRobert Love 	xid = *plast;
509*42e9a92fSRobert Love 	do {
510*42e9a92fSRobert Love 		xid = (xid == max) ? min : xid + 1;
511*42e9a92fSRobert Love 		ep = mp->exches[xid - mp->min_xid];
512*42e9a92fSRobert Love 	} while ((ep != NULL) && (xid != *plast));
513*42e9a92fSRobert Love 
514*42e9a92fSRobert Love 	if (unlikely(ep))
515*42e9a92fSRobert Love 		xid = 0;
516*42e9a92fSRobert Love 	else
517*42e9a92fSRobert Love 		*plast = xid;
518*42e9a92fSRobert Love 
519*42e9a92fSRobert Love 	return xid;
520*42e9a92fSRobert Love }
521*42e9a92fSRobert Love 
522*42e9a92fSRobert Love /*
523*42e9a92fSRobert Love  * fc_exch_alloc - allocate an exchange.
524*42e9a92fSRobert Love  * @mp : ptr to the exchange manager
525*42e9a92fSRobert Love  * @xid: input xid
526*42e9a92fSRobert Love  *
527*42e9a92fSRobert Love  * if xid is supplied zero then assign next free exchange ID
528*42e9a92fSRobert Love  * from exchange manager, otherwise use supplied xid.
529*42e9a92fSRobert Love  * Returns with exch lock held.
530*42e9a92fSRobert Love  */
531*42e9a92fSRobert Love struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp,
532*42e9a92fSRobert Love 			      struct fc_frame *fp, u16 xid)
533*42e9a92fSRobert Love {
534*42e9a92fSRobert Love 	struct fc_exch *ep;
535*42e9a92fSRobert Love 
536*42e9a92fSRobert Love 	/* allocate memory for exchange */
537*42e9a92fSRobert Love 	ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
538*42e9a92fSRobert Love 	if (!ep) {
539*42e9a92fSRobert Love 		atomic_inc(&mp->stats.no_free_exch);
540*42e9a92fSRobert Love 		goto out;
541*42e9a92fSRobert Love 	}
542*42e9a92fSRobert Love 	memset(ep, 0, sizeof(*ep));
543*42e9a92fSRobert Love 
544*42e9a92fSRobert Love 	spin_lock_bh(&mp->em_lock);
545*42e9a92fSRobert Love 	/* alloc xid if input xid 0 */
546*42e9a92fSRobert Love 	if (!xid) {
547*42e9a92fSRobert Love 		/* alloc a new xid */
548*42e9a92fSRobert Love 		xid = fc_em_alloc_xid(mp, fp);
549*42e9a92fSRobert Love 		if (!xid) {
550*42e9a92fSRobert Love 			printk(KERN_ERR "fc_em_alloc_xid() failed\n");
551*42e9a92fSRobert Love 			goto err;
552*42e9a92fSRobert Love 		}
553*42e9a92fSRobert Love 	}
554*42e9a92fSRobert Love 
555*42e9a92fSRobert Love 	fc_exch_hold(ep);	/* hold for exch in mp */
556*42e9a92fSRobert Love 	spin_lock_init(&ep->ex_lock);
557*42e9a92fSRobert Love 	/*
558*42e9a92fSRobert Love 	 * Hold exch lock for caller to prevent fc_exch_reset()
559*42e9a92fSRobert Love 	 * from releasing exch	while fc_exch_alloc() caller is
560*42e9a92fSRobert Love 	 * still working on exch.
561*42e9a92fSRobert Love 	 */
562*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
563*42e9a92fSRobert Love 
564*42e9a92fSRobert Love 	mp->exches[xid - mp->min_xid] = ep;
565*42e9a92fSRobert Love 	list_add_tail(&ep->ex_list, &mp->ex_list);
566*42e9a92fSRobert Love 	fc_seq_alloc(ep, ep->seq_id++);
567*42e9a92fSRobert Love 	mp->total_exches++;
568*42e9a92fSRobert Love 	spin_unlock_bh(&mp->em_lock);
569*42e9a92fSRobert Love 
570*42e9a92fSRobert Love 	/*
571*42e9a92fSRobert Love 	 *  update exchange
572*42e9a92fSRobert Love 	 */
573*42e9a92fSRobert Love 	ep->oxid = ep->xid = xid;
574*42e9a92fSRobert Love 	ep->em = mp;
575*42e9a92fSRobert Love 	ep->lp = mp->lp;
576*42e9a92fSRobert Love 	ep->f_ctl = FC_FC_FIRST_SEQ;	/* next seq is first seq */
577*42e9a92fSRobert Love 	ep->rxid = FC_XID_UNKNOWN;
578*42e9a92fSRobert Love 	ep->class = mp->class;
579*42e9a92fSRobert Love 	INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout);
580*42e9a92fSRobert Love out:
581*42e9a92fSRobert Love 	return ep;
582*42e9a92fSRobert Love err:
583*42e9a92fSRobert Love 	spin_unlock_bh(&mp->em_lock);
584*42e9a92fSRobert Love 	atomic_inc(&mp->stats.no_free_exch_xid);
585*42e9a92fSRobert Love 	mempool_free(ep, mp->ep_pool);
586*42e9a92fSRobert Love 	return NULL;
587*42e9a92fSRobert Love }
588*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_alloc);
589*42e9a92fSRobert Love 
590*42e9a92fSRobert Love /*
591*42e9a92fSRobert Love  * Lookup and hold an exchange.
592*42e9a92fSRobert Love  */
593*42e9a92fSRobert Love static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
594*42e9a92fSRobert Love {
595*42e9a92fSRobert Love 	struct fc_exch *ep = NULL;
596*42e9a92fSRobert Love 
597*42e9a92fSRobert Love 	if ((xid >= mp->min_xid) && (xid <= mp->max_xid)) {
598*42e9a92fSRobert Love 		spin_lock_bh(&mp->em_lock);
599*42e9a92fSRobert Love 		ep = mp->exches[xid - mp->min_xid];
600*42e9a92fSRobert Love 		if (ep) {
601*42e9a92fSRobert Love 			fc_exch_hold(ep);
602*42e9a92fSRobert Love 			WARN_ON(ep->xid != xid);
603*42e9a92fSRobert Love 		}
604*42e9a92fSRobert Love 		spin_unlock_bh(&mp->em_lock);
605*42e9a92fSRobert Love 	}
606*42e9a92fSRobert Love 	return ep;
607*42e9a92fSRobert Love }
608*42e9a92fSRobert Love 
609*42e9a92fSRobert Love void fc_exch_done(struct fc_seq *sp)
610*42e9a92fSRobert Love {
611*42e9a92fSRobert Love 	struct fc_exch *ep = fc_seq_exch(sp);
612*42e9a92fSRobert Love 	int rc;
613*42e9a92fSRobert Love 
614*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
615*42e9a92fSRobert Love 	rc = fc_exch_done_locked(ep);
616*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
617*42e9a92fSRobert Love 	if (!rc)
618*42e9a92fSRobert Love 		fc_exch_mgr_delete_ep(ep);
619*42e9a92fSRobert Love }
620*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_done);
621*42e9a92fSRobert Love 
622*42e9a92fSRobert Love /*
623*42e9a92fSRobert Love  * Allocate a new exchange as responder.
624*42e9a92fSRobert Love  * Sets the responder ID in the frame header.
625*42e9a92fSRobert Love  */
626*42e9a92fSRobert Love static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
627*42e9a92fSRobert Love {
628*42e9a92fSRobert Love 	struct fc_exch *ep;
629*42e9a92fSRobert Love 	struct fc_frame_header *fh;
630*42e9a92fSRobert Love 	u16 rxid;
631*42e9a92fSRobert Love 
632*42e9a92fSRobert Love 	ep = mp->lp->tt.exch_get(mp->lp, fp);
633*42e9a92fSRobert Love 	if (ep) {
634*42e9a92fSRobert Love 		ep->class = fc_frame_class(fp);
635*42e9a92fSRobert Love 
636*42e9a92fSRobert Love 		/*
637*42e9a92fSRobert Love 		 * Set EX_CTX indicating we're responding on this exchange.
638*42e9a92fSRobert Love 		 */
639*42e9a92fSRobert Love 		ep->f_ctl |= FC_FC_EX_CTX;	/* we're responding */
640*42e9a92fSRobert Love 		ep->f_ctl &= ~FC_FC_FIRST_SEQ;	/* not new */
641*42e9a92fSRobert Love 		fh = fc_frame_header_get(fp);
642*42e9a92fSRobert Love 		ep->sid = ntoh24(fh->fh_d_id);
643*42e9a92fSRobert Love 		ep->did = ntoh24(fh->fh_s_id);
644*42e9a92fSRobert Love 		ep->oid = ep->did;
645*42e9a92fSRobert Love 
646*42e9a92fSRobert Love 		/*
647*42e9a92fSRobert Love 		 * Allocated exchange has placed the XID in the
648*42e9a92fSRobert Love 		 * originator field. Move it to the responder field,
649*42e9a92fSRobert Love 		 * and set the originator XID from the frame.
650*42e9a92fSRobert Love 		 */
651*42e9a92fSRobert Love 		ep->rxid = ep->xid;
652*42e9a92fSRobert Love 		ep->oxid = ntohs(fh->fh_ox_id);
653*42e9a92fSRobert Love 		ep->esb_stat |= ESB_ST_RESP | ESB_ST_SEQ_INIT;
654*42e9a92fSRobert Love 		if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0)
655*42e9a92fSRobert Love 			ep->esb_stat &= ~ESB_ST_SEQ_INIT;
656*42e9a92fSRobert Love 
657*42e9a92fSRobert Love 		/*
658*42e9a92fSRobert Love 		 * Set the responder ID in the frame header.
659*42e9a92fSRobert Love 		 * The old one should've been 0xffff.
660*42e9a92fSRobert Love 		 * If it isn't, don't assign one.
661*42e9a92fSRobert Love 		 * Incoming basic link service frames may specify
662*42e9a92fSRobert Love 		 * a referenced RX_ID.
663*42e9a92fSRobert Love 		 */
664*42e9a92fSRobert Love 		if (fh->fh_type != FC_TYPE_BLS) {
665*42e9a92fSRobert Love 			rxid = ntohs(fh->fh_rx_id);
666*42e9a92fSRobert Love 			WARN_ON(rxid != FC_XID_UNKNOWN);
667*42e9a92fSRobert Love 			fh->fh_rx_id = htons(ep->rxid);
668*42e9a92fSRobert Love 		}
669*42e9a92fSRobert Love 		fc_exch_hold(ep);	/* hold for caller */
670*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);	/* lock from exch_get */
671*42e9a92fSRobert Love 	}
672*42e9a92fSRobert Love 	return ep;
673*42e9a92fSRobert Love }
674*42e9a92fSRobert Love 
675*42e9a92fSRobert Love /*
676*42e9a92fSRobert Love  * Find a sequence for receive where the other end is originating the sequence.
677*42e9a92fSRobert Love  * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
678*42e9a92fSRobert Love  * on the ep that should be released by the caller.
679*42e9a92fSRobert Love  */
680*42e9a92fSRobert Love static enum fc_pf_rjt_reason
681*42e9a92fSRobert Love fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
682*42e9a92fSRobert Love {
683*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
684*42e9a92fSRobert Love 	struct fc_exch *ep = NULL;
685*42e9a92fSRobert Love 	struct fc_seq *sp = NULL;
686*42e9a92fSRobert Love 	enum fc_pf_rjt_reason reject = FC_RJT_NONE;
687*42e9a92fSRobert Love 	u32 f_ctl;
688*42e9a92fSRobert Love 	u16 xid;
689*42e9a92fSRobert Love 
690*42e9a92fSRobert Love 	f_ctl = ntoh24(fh->fh_f_ctl);
691*42e9a92fSRobert Love 	WARN_ON((f_ctl & FC_FC_SEQ_CTX) != 0);
692*42e9a92fSRobert Love 
693*42e9a92fSRobert Love 	/*
694*42e9a92fSRobert Love 	 * Lookup or create the exchange if we will be creating the sequence.
695*42e9a92fSRobert Love 	 */
696*42e9a92fSRobert Love 	if (f_ctl & FC_FC_EX_CTX) {
697*42e9a92fSRobert Love 		xid = ntohs(fh->fh_ox_id);	/* we originated exch */
698*42e9a92fSRobert Love 		ep = fc_exch_find(mp, xid);
699*42e9a92fSRobert Love 		if (!ep) {
700*42e9a92fSRobert Love 			atomic_inc(&mp->stats.xid_not_found);
701*42e9a92fSRobert Love 			reject = FC_RJT_OX_ID;
702*42e9a92fSRobert Love 			goto out;
703*42e9a92fSRobert Love 		}
704*42e9a92fSRobert Love 		if (ep->rxid == FC_XID_UNKNOWN)
705*42e9a92fSRobert Love 			ep->rxid = ntohs(fh->fh_rx_id);
706*42e9a92fSRobert Love 		else if (ep->rxid != ntohs(fh->fh_rx_id)) {
707*42e9a92fSRobert Love 			reject = FC_RJT_OX_ID;
708*42e9a92fSRobert Love 			goto rel;
709*42e9a92fSRobert Love 		}
710*42e9a92fSRobert Love 	} else {
711*42e9a92fSRobert Love 		xid = ntohs(fh->fh_rx_id);	/* we are the responder */
712*42e9a92fSRobert Love 
713*42e9a92fSRobert Love 		/*
714*42e9a92fSRobert Love 		 * Special case for MDS issuing an ELS TEST with a
715*42e9a92fSRobert Love 		 * bad rxid of 0.
716*42e9a92fSRobert Love 		 * XXX take this out once we do the proper reject.
717*42e9a92fSRobert Love 		 */
718*42e9a92fSRobert Love 		if (xid == 0 && fh->fh_r_ctl == FC_RCTL_ELS_REQ &&
719*42e9a92fSRobert Love 		    fc_frame_payload_op(fp) == ELS_TEST) {
720*42e9a92fSRobert Love 			fh->fh_rx_id = htons(FC_XID_UNKNOWN);
721*42e9a92fSRobert Love 			xid = FC_XID_UNKNOWN;
722*42e9a92fSRobert Love 		}
723*42e9a92fSRobert Love 
724*42e9a92fSRobert Love 		/*
725*42e9a92fSRobert Love 		 * new sequence - find the exchange
726*42e9a92fSRobert Love 		 */
727*42e9a92fSRobert Love 		ep = fc_exch_find(mp, xid);
728*42e9a92fSRobert Love 		if ((f_ctl & FC_FC_FIRST_SEQ) && fc_sof_is_init(fr_sof(fp))) {
729*42e9a92fSRobert Love 			if (ep) {
730*42e9a92fSRobert Love 				atomic_inc(&mp->stats.xid_busy);
731*42e9a92fSRobert Love 				reject = FC_RJT_RX_ID;
732*42e9a92fSRobert Love 				goto rel;
733*42e9a92fSRobert Love 			}
734*42e9a92fSRobert Love 			ep = fc_exch_resp(mp, fp);
735*42e9a92fSRobert Love 			if (!ep) {
736*42e9a92fSRobert Love 				reject = FC_RJT_EXCH_EST;	/* XXX */
737*42e9a92fSRobert Love 				goto out;
738*42e9a92fSRobert Love 			}
739*42e9a92fSRobert Love 			xid = ep->xid;	/* get our XID */
740*42e9a92fSRobert Love 		} else if (!ep) {
741*42e9a92fSRobert Love 			atomic_inc(&mp->stats.xid_not_found);
742*42e9a92fSRobert Love 			reject = FC_RJT_RX_ID;	/* XID not found */
743*42e9a92fSRobert Love 			goto out;
744*42e9a92fSRobert Love 		}
745*42e9a92fSRobert Love 	}
746*42e9a92fSRobert Love 
747*42e9a92fSRobert Love 	/*
748*42e9a92fSRobert Love 	 * At this point, we have the exchange held.
749*42e9a92fSRobert Love 	 * Find or create the sequence.
750*42e9a92fSRobert Love 	 */
751*42e9a92fSRobert Love 	if (fc_sof_is_init(fr_sof(fp))) {
752*42e9a92fSRobert Love 		sp = fc_seq_start_next(&ep->seq);
753*42e9a92fSRobert Love 		if (!sp) {
754*42e9a92fSRobert Love 			reject = FC_RJT_SEQ_XS;	/* exchange shortage */
755*42e9a92fSRobert Love 			goto rel;
756*42e9a92fSRobert Love 		}
757*42e9a92fSRobert Love 		sp->id = fh->fh_seq_id;
758*42e9a92fSRobert Love 		sp->ssb_stat |= SSB_ST_RESP;
759*42e9a92fSRobert Love 	} else {
760*42e9a92fSRobert Love 		sp = &ep->seq;
761*42e9a92fSRobert Love 		if (sp->id != fh->fh_seq_id) {
762*42e9a92fSRobert Love 			atomic_inc(&mp->stats.seq_not_found);
763*42e9a92fSRobert Love 			reject = FC_RJT_SEQ_ID;	/* sequence/exch should exist */
764*42e9a92fSRobert Love 			goto rel;
765*42e9a92fSRobert Love 		}
766*42e9a92fSRobert Love 	}
767*42e9a92fSRobert Love 	WARN_ON(ep != fc_seq_exch(sp));
768*42e9a92fSRobert Love 
769*42e9a92fSRobert Love 	if (f_ctl & FC_FC_SEQ_INIT)
770*42e9a92fSRobert Love 		ep->esb_stat |= ESB_ST_SEQ_INIT;
771*42e9a92fSRobert Love 
772*42e9a92fSRobert Love 	fr_seq(fp) = sp;
773*42e9a92fSRobert Love out:
774*42e9a92fSRobert Love 	return reject;
775*42e9a92fSRobert Love rel:
776*42e9a92fSRobert Love 	fc_exch_done(&ep->seq);
777*42e9a92fSRobert Love 	fc_exch_release(ep);	/* hold from fc_exch_find/fc_exch_resp */
778*42e9a92fSRobert Love 	return reject;
779*42e9a92fSRobert Love }
780*42e9a92fSRobert Love 
781*42e9a92fSRobert Love /*
782*42e9a92fSRobert Love  * Find the sequence for a frame being received.
783*42e9a92fSRobert Love  * We originated the sequence, so it should be found.
784*42e9a92fSRobert Love  * We may or may not have originated the exchange.
785*42e9a92fSRobert Love  * Does not hold the sequence for the caller.
786*42e9a92fSRobert Love  */
787*42e9a92fSRobert Love static struct fc_seq *fc_seq_lookup_orig(struct fc_exch_mgr *mp,
788*42e9a92fSRobert Love 					 struct fc_frame *fp)
789*42e9a92fSRobert Love {
790*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
791*42e9a92fSRobert Love 	struct fc_exch *ep;
792*42e9a92fSRobert Love 	struct fc_seq *sp = NULL;
793*42e9a92fSRobert Love 	u32 f_ctl;
794*42e9a92fSRobert Love 	u16 xid;
795*42e9a92fSRobert Love 
796*42e9a92fSRobert Love 	f_ctl = ntoh24(fh->fh_f_ctl);
797*42e9a92fSRobert Love 	WARN_ON((f_ctl & FC_FC_SEQ_CTX) != FC_FC_SEQ_CTX);
798*42e9a92fSRobert Love 	xid = ntohs((f_ctl & FC_FC_EX_CTX) ? fh->fh_ox_id : fh->fh_rx_id);
799*42e9a92fSRobert Love 	ep = fc_exch_find(mp, xid);
800*42e9a92fSRobert Love 	if (!ep)
801*42e9a92fSRobert Love 		return NULL;
802*42e9a92fSRobert Love 	if (ep->seq.id == fh->fh_seq_id) {
803*42e9a92fSRobert Love 		/*
804*42e9a92fSRobert Love 		 * Save the RX_ID if we didn't previously know it.
805*42e9a92fSRobert Love 		 */
806*42e9a92fSRobert Love 		sp = &ep->seq;
807*42e9a92fSRobert Love 		if ((f_ctl & FC_FC_EX_CTX) != 0 &&
808*42e9a92fSRobert Love 		    ep->rxid == FC_XID_UNKNOWN) {
809*42e9a92fSRobert Love 			ep->rxid = ntohs(fh->fh_rx_id);
810*42e9a92fSRobert Love 		}
811*42e9a92fSRobert Love 	}
812*42e9a92fSRobert Love 	fc_exch_release(ep);
813*42e9a92fSRobert Love 	return sp;
814*42e9a92fSRobert Love }
815*42e9a92fSRobert Love 
816*42e9a92fSRobert Love /*
817*42e9a92fSRobert Love  * Set addresses for an exchange.
818*42e9a92fSRobert Love  * Note this must be done before the first sequence of the exchange is sent.
819*42e9a92fSRobert Love  */
820*42e9a92fSRobert Love static void fc_exch_set_addr(struct fc_exch *ep,
821*42e9a92fSRobert Love 			     u32 orig_id, u32 resp_id)
822*42e9a92fSRobert Love {
823*42e9a92fSRobert Love 	ep->oid = orig_id;
824*42e9a92fSRobert Love 	if (ep->esb_stat & ESB_ST_RESP) {
825*42e9a92fSRobert Love 		ep->sid = resp_id;
826*42e9a92fSRobert Love 		ep->did = orig_id;
827*42e9a92fSRobert Love 	} else {
828*42e9a92fSRobert Love 		ep->sid = orig_id;
829*42e9a92fSRobert Love 		ep->did = resp_id;
830*42e9a92fSRobert Love 	}
831*42e9a92fSRobert Love }
832*42e9a92fSRobert Love 
833*42e9a92fSRobert Love static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp)
834*42e9a92fSRobert Love {
835*42e9a92fSRobert Love 	struct fc_exch *ep = fc_seq_exch(sp);
836*42e9a92fSRobert Love 
837*42e9a92fSRobert Love 	sp = fc_seq_alloc(ep, ep->seq_id++);
838*42e9a92fSRobert Love 	FC_DEBUG_EXCH("exch %4x f_ctl %6x seq %2x\n",
839*42e9a92fSRobert Love 		      ep->xid, ep->f_ctl, sp->id);
840*42e9a92fSRobert Love 	return sp;
841*42e9a92fSRobert Love }
842*42e9a92fSRobert Love /*
843*42e9a92fSRobert Love  * Allocate a new sequence on the same exchange as the supplied sequence.
844*42e9a92fSRobert Love  * This will never return NULL.
845*42e9a92fSRobert Love  */
846*42e9a92fSRobert Love struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
847*42e9a92fSRobert Love {
848*42e9a92fSRobert Love 	struct fc_exch *ep = fc_seq_exch(sp);
849*42e9a92fSRobert Love 
850*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
851*42e9a92fSRobert Love 	WARN_ON((ep->esb_stat & ESB_ST_COMPLETE) != 0);
852*42e9a92fSRobert Love 	sp = fc_seq_start_next_locked(sp);
853*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
854*42e9a92fSRobert Love 
855*42e9a92fSRobert Love 	return sp;
856*42e9a92fSRobert Love }
857*42e9a92fSRobert Love EXPORT_SYMBOL(fc_seq_start_next);
858*42e9a92fSRobert Love 
859*42e9a92fSRobert Love int fc_seq_send(struct fc_lport *lp, struct fc_seq *sp, struct fc_frame *fp)
860*42e9a92fSRobert Love {
861*42e9a92fSRobert Love 	struct fc_exch *ep;
862*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
863*42e9a92fSRobert Love 	int error;
864*42e9a92fSRobert Love 	u32	f_ctl;
865*42e9a92fSRobert Love 
866*42e9a92fSRobert Love 	ep = fc_seq_exch(sp);
867*42e9a92fSRobert Love 	WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT);
868*42e9a92fSRobert Love 
869*42e9a92fSRobert Love 	f_ctl = ntoh24(fh->fh_f_ctl);
870*42e9a92fSRobert Love 	fc_exch_setup_hdr(ep, fp, f_ctl);
871*42e9a92fSRobert Love 
872*42e9a92fSRobert Love 	/*
873*42e9a92fSRobert Love 	 * update sequence count if this frame is carrying
874*42e9a92fSRobert Love 	 * multiple FC frames when sequence offload is enabled
875*42e9a92fSRobert Love 	 * by LLD.
876*42e9a92fSRobert Love 	 */
877*42e9a92fSRobert Love 	if (fr_max_payload(fp))
878*42e9a92fSRobert Love 		sp->cnt += DIV_ROUND_UP((fr_len(fp) - sizeof(*fh)),
879*42e9a92fSRobert Love 					fr_max_payload(fp));
880*42e9a92fSRobert Love 	else
881*42e9a92fSRobert Love 		sp->cnt++;
882*42e9a92fSRobert Love 
883*42e9a92fSRobert Love 	/*
884*42e9a92fSRobert Love 	 * Send the frame.
885*42e9a92fSRobert Love 	 */
886*42e9a92fSRobert Love 	error = lp->tt.frame_send(lp, fp);
887*42e9a92fSRobert Love 
888*42e9a92fSRobert Love 	/*
889*42e9a92fSRobert Love 	 * Update the exchange and sequence flags,
890*42e9a92fSRobert Love 	 * assuming all frames for the sequence have been sent.
891*42e9a92fSRobert Love 	 * We can only be called to send once for each sequence.
892*42e9a92fSRobert Love 	 */
893*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
894*42e9a92fSRobert Love 	ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ;	/* not first seq */
895*42e9a92fSRobert Love 	if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT))
896*42e9a92fSRobert Love 		ep->esb_stat &= ~ESB_ST_SEQ_INIT;
897*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
898*42e9a92fSRobert Love 	return error;
899*42e9a92fSRobert Love }
900*42e9a92fSRobert Love EXPORT_SYMBOL(fc_seq_send);
901*42e9a92fSRobert Love 
902*42e9a92fSRobert Love void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd,
903*42e9a92fSRobert Love 			 struct fc_seq_els_data *els_data)
904*42e9a92fSRobert Love {
905*42e9a92fSRobert Love 	switch (els_cmd) {
906*42e9a92fSRobert Love 	case ELS_LS_RJT:
907*42e9a92fSRobert Love 		fc_seq_ls_rjt(sp, els_data->reason, els_data->explan);
908*42e9a92fSRobert Love 		break;
909*42e9a92fSRobert Love 	case ELS_LS_ACC:
910*42e9a92fSRobert Love 		fc_seq_ls_acc(sp);
911*42e9a92fSRobert Love 		break;
912*42e9a92fSRobert Love 	case ELS_RRQ:
913*42e9a92fSRobert Love 		fc_exch_els_rrq(sp, els_data->fp);
914*42e9a92fSRobert Love 		break;
915*42e9a92fSRobert Love 	case ELS_REC:
916*42e9a92fSRobert Love 		fc_exch_els_rec(sp, els_data->fp);
917*42e9a92fSRobert Love 		break;
918*42e9a92fSRobert Love 	default:
919*42e9a92fSRobert Love 		FC_DBG("Invalid ELS CMD:%x\n", els_cmd);
920*42e9a92fSRobert Love 	}
921*42e9a92fSRobert Love }
922*42e9a92fSRobert Love EXPORT_SYMBOL(fc_seq_els_rsp_send);
923*42e9a92fSRobert Love 
924*42e9a92fSRobert Love /*
925*42e9a92fSRobert Love  * Send a sequence, which is also the last sequence in the exchange.
926*42e9a92fSRobert Love  */
927*42e9a92fSRobert Love static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp,
928*42e9a92fSRobert Love 			     enum fc_rctl rctl, enum fc_fh_type fh_type)
929*42e9a92fSRobert Love {
930*42e9a92fSRobert Love 	u32 f_ctl;
931*42e9a92fSRobert Love 	struct fc_exch *ep = fc_seq_exch(sp);
932*42e9a92fSRobert Love 
933*42e9a92fSRobert Love 	f_ctl = FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT;
934*42e9a92fSRobert Love 	f_ctl |= ep->f_ctl;
935*42e9a92fSRobert Love 	fc_fill_fc_hdr(fp, rctl, ep->did, ep->sid, fh_type, f_ctl, 0);
936*42e9a92fSRobert Love 	fc_seq_send(ep->lp, sp, fp);
937*42e9a92fSRobert Love }
938*42e9a92fSRobert Love 
939*42e9a92fSRobert Love /*
940*42e9a92fSRobert Love  * Send ACK_1 (or equiv.) indicating we received something.
941*42e9a92fSRobert Love  * The frame we're acking is supplied.
942*42e9a92fSRobert Love  */
943*42e9a92fSRobert Love static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
944*42e9a92fSRobert Love {
945*42e9a92fSRobert Love 	struct fc_frame *fp;
946*42e9a92fSRobert Love 	struct fc_frame_header *rx_fh;
947*42e9a92fSRobert Love 	struct fc_frame_header *fh;
948*42e9a92fSRobert Love 	struct fc_exch *ep = fc_seq_exch(sp);
949*42e9a92fSRobert Love 	struct fc_lport *lp = ep->lp;
950*42e9a92fSRobert Love 	unsigned int f_ctl;
951*42e9a92fSRobert Love 
952*42e9a92fSRobert Love 	/*
953*42e9a92fSRobert Love 	 * Don't send ACKs for class 3.
954*42e9a92fSRobert Love 	 */
955*42e9a92fSRobert Love 	if (fc_sof_needs_ack(fr_sof(rx_fp))) {
956*42e9a92fSRobert Love 		fp = fc_frame_alloc(lp, 0);
957*42e9a92fSRobert Love 		if (!fp)
958*42e9a92fSRobert Love 			return;
959*42e9a92fSRobert Love 
960*42e9a92fSRobert Love 		fh = fc_frame_header_get(fp);
961*42e9a92fSRobert Love 		fh->fh_r_ctl = FC_RCTL_ACK_1;
962*42e9a92fSRobert Love 		fh->fh_type = FC_TYPE_BLS;
963*42e9a92fSRobert Love 
964*42e9a92fSRobert Love 		/*
965*42e9a92fSRobert Love 		 * Form f_ctl by inverting EX_CTX and SEQ_CTX (bits 23, 22).
966*42e9a92fSRobert Love 		 * Echo FIRST_SEQ, LAST_SEQ, END_SEQ, END_CONN, SEQ_INIT.
967*42e9a92fSRobert Love 		 * Bits 9-8 are meaningful (retransmitted or unidirectional).
968*42e9a92fSRobert Love 		 * Last ACK uses bits 7-6 (continue sequence),
969*42e9a92fSRobert Love 		 * bits 5-4 are meaningful (what kind of ACK to use).
970*42e9a92fSRobert Love 		 */
971*42e9a92fSRobert Love 		rx_fh = fc_frame_header_get(rx_fp);
972*42e9a92fSRobert Love 		f_ctl = ntoh24(rx_fh->fh_f_ctl);
973*42e9a92fSRobert Love 		f_ctl &= FC_FC_EX_CTX | FC_FC_SEQ_CTX |
974*42e9a92fSRobert Love 			FC_FC_FIRST_SEQ | FC_FC_LAST_SEQ |
975*42e9a92fSRobert Love 			FC_FC_END_SEQ | FC_FC_END_CONN | FC_FC_SEQ_INIT |
976*42e9a92fSRobert Love 			FC_FC_RETX_SEQ | FC_FC_UNI_TX;
977*42e9a92fSRobert Love 		f_ctl ^= FC_FC_EX_CTX | FC_FC_SEQ_CTX;
978*42e9a92fSRobert Love 		hton24(fh->fh_f_ctl, f_ctl);
979*42e9a92fSRobert Love 
980*42e9a92fSRobert Love 		fc_exch_setup_hdr(ep, fp, f_ctl);
981*42e9a92fSRobert Love 		fh->fh_seq_id = rx_fh->fh_seq_id;
982*42e9a92fSRobert Love 		fh->fh_seq_cnt = rx_fh->fh_seq_cnt;
983*42e9a92fSRobert Love 		fh->fh_parm_offset = htonl(1);	/* ack single frame */
984*42e9a92fSRobert Love 
985*42e9a92fSRobert Love 		fr_sof(fp) = fr_sof(rx_fp);
986*42e9a92fSRobert Love 		if (f_ctl & FC_FC_END_SEQ)
987*42e9a92fSRobert Love 			fr_eof(fp) = FC_EOF_T;
988*42e9a92fSRobert Love 		else
989*42e9a92fSRobert Love 			fr_eof(fp) = FC_EOF_N;
990*42e9a92fSRobert Love 
991*42e9a92fSRobert Love 		(void) lp->tt.frame_send(lp, fp);
992*42e9a92fSRobert Love 	}
993*42e9a92fSRobert Love }
994*42e9a92fSRobert Love 
995*42e9a92fSRobert Love /*
996*42e9a92fSRobert Love  * Send BLS Reject.
997*42e9a92fSRobert Love  * This is for rejecting BA_ABTS only.
998*42e9a92fSRobert Love  */
999*42e9a92fSRobert Love static void
1000*42e9a92fSRobert Love fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason,
1001*42e9a92fSRobert Love 		    enum fc_ba_rjt_explan explan)
1002*42e9a92fSRobert Love {
1003*42e9a92fSRobert Love 	struct fc_frame *fp;
1004*42e9a92fSRobert Love 	struct fc_frame_header *rx_fh;
1005*42e9a92fSRobert Love 	struct fc_frame_header *fh;
1006*42e9a92fSRobert Love 	struct fc_ba_rjt *rp;
1007*42e9a92fSRobert Love 	struct fc_lport *lp;
1008*42e9a92fSRobert Love 	unsigned int f_ctl;
1009*42e9a92fSRobert Love 
1010*42e9a92fSRobert Love 	lp = fr_dev(rx_fp);
1011*42e9a92fSRobert Love 	fp = fc_frame_alloc(lp, sizeof(*rp));
1012*42e9a92fSRobert Love 	if (!fp)
1013*42e9a92fSRobert Love 		return;
1014*42e9a92fSRobert Love 	fh = fc_frame_header_get(fp);
1015*42e9a92fSRobert Love 	rx_fh = fc_frame_header_get(rx_fp);
1016*42e9a92fSRobert Love 
1017*42e9a92fSRobert Love 	memset(fh, 0, sizeof(*fh) + sizeof(*rp));
1018*42e9a92fSRobert Love 
1019*42e9a92fSRobert Love 	rp = fc_frame_payload_get(fp, sizeof(*rp));
1020*42e9a92fSRobert Love 	rp->br_reason = reason;
1021*42e9a92fSRobert Love 	rp->br_explan = explan;
1022*42e9a92fSRobert Love 
1023*42e9a92fSRobert Love 	/*
1024*42e9a92fSRobert Love 	 * seq_id, cs_ctl, df_ctl and param/offset are zero.
1025*42e9a92fSRobert Love 	 */
1026*42e9a92fSRobert Love 	memcpy(fh->fh_s_id, rx_fh->fh_d_id, 3);
1027*42e9a92fSRobert Love 	memcpy(fh->fh_d_id, rx_fh->fh_s_id, 3);
1028*42e9a92fSRobert Love 	fh->fh_ox_id = rx_fh->fh_rx_id;
1029*42e9a92fSRobert Love 	fh->fh_rx_id = rx_fh->fh_ox_id;
1030*42e9a92fSRobert Love 	fh->fh_seq_cnt = rx_fh->fh_seq_cnt;
1031*42e9a92fSRobert Love 	fh->fh_r_ctl = FC_RCTL_BA_RJT;
1032*42e9a92fSRobert Love 	fh->fh_type = FC_TYPE_BLS;
1033*42e9a92fSRobert Love 
1034*42e9a92fSRobert Love 	/*
1035*42e9a92fSRobert Love 	 * Form f_ctl by inverting EX_CTX and SEQ_CTX (bits 23, 22).
1036*42e9a92fSRobert Love 	 * Echo FIRST_SEQ, LAST_SEQ, END_SEQ, END_CONN, SEQ_INIT.
1037*42e9a92fSRobert Love 	 * Bits 9-8 are meaningful (retransmitted or unidirectional).
1038*42e9a92fSRobert Love 	 * Last ACK uses bits 7-6 (continue sequence),
1039*42e9a92fSRobert Love 	 * bits 5-4 are meaningful (what kind of ACK to use).
1040*42e9a92fSRobert Love 	 * Always set LAST_SEQ, END_SEQ.
1041*42e9a92fSRobert Love 	 */
1042*42e9a92fSRobert Love 	f_ctl = ntoh24(rx_fh->fh_f_ctl);
1043*42e9a92fSRobert Love 	f_ctl &= FC_FC_EX_CTX | FC_FC_SEQ_CTX |
1044*42e9a92fSRobert Love 		FC_FC_END_CONN | FC_FC_SEQ_INIT |
1045*42e9a92fSRobert Love 		FC_FC_RETX_SEQ | FC_FC_UNI_TX;
1046*42e9a92fSRobert Love 	f_ctl ^= FC_FC_EX_CTX | FC_FC_SEQ_CTX;
1047*42e9a92fSRobert Love 	f_ctl |= FC_FC_LAST_SEQ | FC_FC_END_SEQ;
1048*42e9a92fSRobert Love 	f_ctl &= ~FC_FC_FIRST_SEQ;
1049*42e9a92fSRobert Love 	hton24(fh->fh_f_ctl, f_ctl);
1050*42e9a92fSRobert Love 
1051*42e9a92fSRobert Love 	fr_sof(fp) = fc_sof_class(fr_sof(rx_fp));
1052*42e9a92fSRobert Love 	fr_eof(fp) = FC_EOF_T;
1053*42e9a92fSRobert Love 	if (fc_sof_needs_ack(fr_sof(fp)))
1054*42e9a92fSRobert Love 		fr_eof(fp) = FC_EOF_N;
1055*42e9a92fSRobert Love 
1056*42e9a92fSRobert Love 	(void) lp->tt.frame_send(lp, fp);
1057*42e9a92fSRobert Love }
1058*42e9a92fSRobert Love 
1059*42e9a92fSRobert Love /*
1060*42e9a92fSRobert Love  * Handle an incoming ABTS.  This would be for target mode usually,
1061*42e9a92fSRobert Love  * but could be due to lost FCP transfer ready, confirm or RRQ.
1062*42e9a92fSRobert Love  * We always handle this as an exchange abort, ignoring the parameter.
1063*42e9a92fSRobert Love  */
1064*42e9a92fSRobert Love static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
1065*42e9a92fSRobert Love {
1066*42e9a92fSRobert Love 	struct fc_frame *fp;
1067*42e9a92fSRobert Love 	struct fc_ba_acc *ap;
1068*42e9a92fSRobert Love 	struct fc_frame_header *fh;
1069*42e9a92fSRobert Love 	struct fc_seq *sp;
1070*42e9a92fSRobert Love 
1071*42e9a92fSRobert Love 	if (!ep)
1072*42e9a92fSRobert Love 		goto reject;
1073*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
1074*42e9a92fSRobert Love 	if (ep->esb_stat & ESB_ST_COMPLETE) {
1075*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
1076*42e9a92fSRobert Love 		goto reject;
1077*42e9a92fSRobert Love 	}
1078*42e9a92fSRobert Love 	if (!(ep->esb_stat & ESB_ST_REC_QUAL))
1079*42e9a92fSRobert Love 		fc_exch_hold(ep);		/* hold for REC_QUAL */
1080*42e9a92fSRobert Love 	ep->esb_stat |= ESB_ST_ABNORMAL | ESB_ST_REC_QUAL;
1081*42e9a92fSRobert Love 	fc_exch_timer_set_locked(ep, ep->r_a_tov);
1082*42e9a92fSRobert Love 
1083*42e9a92fSRobert Love 	fp = fc_frame_alloc(ep->lp, sizeof(*ap));
1084*42e9a92fSRobert Love 	if (!fp) {
1085*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
1086*42e9a92fSRobert Love 		goto free;
1087*42e9a92fSRobert Love 	}
1088*42e9a92fSRobert Love 	fh = fc_frame_header_get(fp);
1089*42e9a92fSRobert Love 	ap = fc_frame_payload_get(fp, sizeof(*ap));
1090*42e9a92fSRobert Love 	memset(ap, 0, sizeof(*ap));
1091*42e9a92fSRobert Love 	sp = &ep->seq;
1092*42e9a92fSRobert Love 	ap->ba_high_seq_cnt = htons(0xffff);
1093*42e9a92fSRobert Love 	if (sp->ssb_stat & SSB_ST_RESP) {
1094*42e9a92fSRobert Love 		ap->ba_seq_id = sp->id;
1095*42e9a92fSRobert Love 		ap->ba_seq_id_val = FC_BA_SEQ_ID_VAL;
1096*42e9a92fSRobert Love 		ap->ba_high_seq_cnt = fh->fh_seq_cnt;
1097*42e9a92fSRobert Love 		ap->ba_low_seq_cnt = htons(sp->cnt);
1098*42e9a92fSRobert Love 	}
1099*42e9a92fSRobert Love 	sp = fc_seq_start_next(sp);
1100*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1101*42e9a92fSRobert Love 	fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS);
1102*42e9a92fSRobert Love 	fc_frame_free(rx_fp);
1103*42e9a92fSRobert Love 	return;
1104*42e9a92fSRobert Love 
1105*42e9a92fSRobert Love reject:
1106*42e9a92fSRobert Love 	fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID);
1107*42e9a92fSRobert Love free:
1108*42e9a92fSRobert Love 	fc_frame_free(rx_fp);
1109*42e9a92fSRobert Love }
1110*42e9a92fSRobert Love 
1111*42e9a92fSRobert Love /*
1112*42e9a92fSRobert Love  * Handle receive where the other end is originating the sequence.
1113*42e9a92fSRobert Love  */
1114*42e9a92fSRobert Love static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp,
1115*42e9a92fSRobert Love 			     struct fc_frame *fp)
1116*42e9a92fSRobert Love {
1117*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
1118*42e9a92fSRobert Love 	struct fc_seq *sp = NULL;
1119*42e9a92fSRobert Love 	struct fc_exch *ep = NULL;
1120*42e9a92fSRobert Love 	enum fc_sof sof;
1121*42e9a92fSRobert Love 	enum fc_eof eof;
1122*42e9a92fSRobert Love 	u32 f_ctl;
1123*42e9a92fSRobert Love 	enum fc_pf_rjt_reason reject;
1124*42e9a92fSRobert Love 
1125*42e9a92fSRobert Love 	fr_seq(fp) = NULL;
1126*42e9a92fSRobert Love 	reject = fc_seq_lookup_recip(mp, fp);
1127*42e9a92fSRobert Love 	if (reject == FC_RJT_NONE) {
1128*42e9a92fSRobert Love 		sp = fr_seq(fp);	/* sequence will be held */
1129*42e9a92fSRobert Love 		ep = fc_seq_exch(sp);
1130*42e9a92fSRobert Love 		sof = fr_sof(fp);
1131*42e9a92fSRobert Love 		eof = fr_eof(fp);
1132*42e9a92fSRobert Love 		f_ctl = ntoh24(fh->fh_f_ctl);
1133*42e9a92fSRobert Love 		fc_seq_send_ack(sp, fp);
1134*42e9a92fSRobert Love 
1135*42e9a92fSRobert Love 		/*
1136*42e9a92fSRobert Love 		 * Call the receive function.
1137*42e9a92fSRobert Love 		 *
1138*42e9a92fSRobert Love 		 * The receive function may allocate a new sequence
1139*42e9a92fSRobert Love 		 * over the old one, so we shouldn't change the
1140*42e9a92fSRobert Love 		 * sequence after this.
1141*42e9a92fSRobert Love 		 *
1142*42e9a92fSRobert Love 		 * The frame will be freed by the receive function.
1143*42e9a92fSRobert Love 		 * If new exch resp handler is valid then call that
1144*42e9a92fSRobert Love 		 * first.
1145*42e9a92fSRobert Love 		 */
1146*42e9a92fSRobert Love 		if (ep->resp)
1147*42e9a92fSRobert Love 			ep->resp(sp, fp, ep->arg);
1148*42e9a92fSRobert Love 		else
1149*42e9a92fSRobert Love 			lp->tt.lport_recv(lp, sp, fp);
1150*42e9a92fSRobert Love 		fc_exch_release(ep);	/* release from lookup */
1151*42e9a92fSRobert Love 	} else {
1152*42e9a92fSRobert Love 		FC_DEBUG_EXCH("exch/seq lookup failed: reject %x\n", reject);
1153*42e9a92fSRobert Love 		fc_frame_free(fp);
1154*42e9a92fSRobert Love 	}
1155*42e9a92fSRobert Love }
1156*42e9a92fSRobert Love 
1157*42e9a92fSRobert Love /*
1158*42e9a92fSRobert Love  * Handle receive where the other end is originating the sequence in
1159*42e9a92fSRobert Love  * response to our exchange.
1160*42e9a92fSRobert Love  */
1161*42e9a92fSRobert Love static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1162*42e9a92fSRobert Love {
1163*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
1164*42e9a92fSRobert Love 	struct fc_seq *sp;
1165*42e9a92fSRobert Love 	struct fc_exch *ep;
1166*42e9a92fSRobert Love 	enum fc_sof sof;
1167*42e9a92fSRobert Love 	u32 f_ctl;
1168*42e9a92fSRobert Love 	void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
1169*42e9a92fSRobert Love 	void *ex_resp_arg;
1170*42e9a92fSRobert Love 	int rc;
1171*42e9a92fSRobert Love 
1172*42e9a92fSRobert Love 	ep = fc_exch_find(mp, ntohs(fh->fh_ox_id));
1173*42e9a92fSRobert Love 	if (!ep) {
1174*42e9a92fSRobert Love 		atomic_inc(&mp->stats.xid_not_found);
1175*42e9a92fSRobert Love 		goto out;
1176*42e9a92fSRobert Love 	}
1177*42e9a92fSRobert Love 	if (ep->rxid == FC_XID_UNKNOWN)
1178*42e9a92fSRobert Love 		ep->rxid = ntohs(fh->fh_rx_id);
1179*42e9a92fSRobert Love 	if (ep->sid != 0 && ep->sid != ntoh24(fh->fh_d_id)) {
1180*42e9a92fSRobert Love 		atomic_inc(&mp->stats.xid_not_found);
1181*42e9a92fSRobert Love 		goto rel;
1182*42e9a92fSRobert Love 	}
1183*42e9a92fSRobert Love 	if (ep->did != ntoh24(fh->fh_s_id) &&
1184*42e9a92fSRobert Love 	    ep->did != FC_FID_FLOGI) {
1185*42e9a92fSRobert Love 		atomic_inc(&mp->stats.xid_not_found);
1186*42e9a92fSRobert Love 		goto rel;
1187*42e9a92fSRobert Love 	}
1188*42e9a92fSRobert Love 	sof = fr_sof(fp);
1189*42e9a92fSRobert Love 	if (fc_sof_is_init(sof)) {
1190*42e9a92fSRobert Love 		sp = fc_seq_start_next(&ep->seq);
1191*42e9a92fSRobert Love 		sp->id = fh->fh_seq_id;
1192*42e9a92fSRobert Love 		sp->ssb_stat |= SSB_ST_RESP;
1193*42e9a92fSRobert Love 	} else {
1194*42e9a92fSRobert Love 		sp = &ep->seq;
1195*42e9a92fSRobert Love 		if (sp->id != fh->fh_seq_id) {
1196*42e9a92fSRobert Love 			atomic_inc(&mp->stats.seq_not_found);
1197*42e9a92fSRobert Love 			goto rel;
1198*42e9a92fSRobert Love 		}
1199*42e9a92fSRobert Love 	}
1200*42e9a92fSRobert Love 	f_ctl = ntoh24(fh->fh_f_ctl);
1201*42e9a92fSRobert Love 	fr_seq(fp) = sp;
1202*42e9a92fSRobert Love 	if (f_ctl & FC_FC_SEQ_INIT)
1203*42e9a92fSRobert Love 		ep->esb_stat |= ESB_ST_SEQ_INIT;
1204*42e9a92fSRobert Love 
1205*42e9a92fSRobert Love 	if (fc_sof_needs_ack(sof))
1206*42e9a92fSRobert Love 		fc_seq_send_ack(sp, fp);
1207*42e9a92fSRobert Love 	resp = ep->resp;
1208*42e9a92fSRobert Love 	ex_resp_arg = ep->arg;
1209*42e9a92fSRobert Love 
1210*42e9a92fSRobert Love 	if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T &&
1211*42e9a92fSRobert Love 	    (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==
1212*42e9a92fSRobert Love 	    (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) {
1213*42e9a92fSRobert Love 		spin_lock_bh(&ep->ex_lock);
1214*42e9a92fSRobert Love 		rc = fc_exch_done_locked(ep);
1215*42e9a92fSRobert Love 		WARN_ON(fc_seq_exch(sp) != ep);
1216*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
1217*42e9a92fSRobert Love 		if (!rc)
1218*42e9a92fSRobert Love 			fc_exch_mgr_delete_ep(ep);
1219*42e9a92fSRobert Love 	}
1220*42e9a92fSRobert Love 
1221*42e9a92fSRobert Love 	/*
1222*42e9a92fSRobert Love 	 * Call the receive function.
1223*42e9a92fSRobert Love 	 * The sequence is held (has a refcnt) for us,
1224*42e9a92fSRobert Love 	 * but not for the receive function.
1225*42e9a92fSRobert Love 	 *
1226*42e9a92fSRobert Love 	 * The receive function may allocate a new sequence
1227*42e9a92fSRobert Love 	 * over the old one, so we shouldn't change the
1228*42e9a92fSRobert Love 	 * sequence after this.
1229*42e9a92fSRobert Love 	 *
1230*42e9a92fSRobert Love 	 * The frame will be freed by the receive function.
1231*42e9a92fSRobert Love 	 * If new exch resp handler is valid then call that
1232*42e9a92fSRobert Love 	 * first.
1233*42e9a92fSRobert Love 	 */
1234*42e9a92fSRobert Love 	if (resp)
1235*42e9a92fSRobert Love 		resp(sp, fp, ex_resp_arg);
1236*42e9a92fSRobert Love 	else
1237*42e9a92fSRobert Love 		fc_frame_free(fp);
1238*42e9a92fSRobert Love 	fc_exch_release(ep);
1239*42e9a92fSRobert Love 	return;
1240*42e9a92fSRobert Love rel:
1241*42e9a92fSRobert Love 	fc_exch_release(ep);
1242*42e9a92fSRobert Love out:
1243*42e9a92fSRobert Love 	fc_frame_free(fp);
1244*42e9a92fSRobert Love }
1245*42e9a92fSRobert Love 
1246*42e9a92fSRobert Love /*
1247*42e9a92fSRobert Love  * Handle receive for a sequence where other end is responding to our sequence.
1248*42e9a92fSRobert Love  */
1249*42e9a92fSRobert Love static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1250*42e9a92fSRobert Love {
1251*42e9a92fSRobert Love 	struct fc_seq *sp;
1252*42e9a92fSRobert Love 
1253*42e9a92fSRobert Love 	sp = fc_seq_lookup_orig(mp, fp);	/* doesn't hold sequence */
1254*42e9a92fSRobert Love 	if (!sp) {
1255*42e9a92fSRobert Love 		atomic_inc(&mp->stats.xid_not_found);
1256*42e9a92fSRobert Love 		FC_DEBUG_EXCH("seq lookup failed\n");
1257*42e9a92fSRobert Love 	} else {
1258*42e9a92fSRobert Love 		atomic_inc(&mp->stats.non_bls_resp);
1259*42e9a92fSRobert Love 		FC_DEBUG_EXCH("non-BLS response to sequence");
1260*42e9a92fSRobert Love 	}
1261*42e9a92fSRobert Love 	fc_frame_free(fp);
1262*42e9a92fSRobert Love }
1263*42e9a92fSRobert Love 
1264*42e9a92fSRobert Love /*
1265*42e9a92fSRobert Love  * Handle the response to an ABTS for exchange or sequence.
1266*42e9a92fSRobert Love  * This can be BA_ACC or BA_RJT.
1267*42e9a92fSRobert Love  */
1268*42e9a92fSRobert Love static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1269*42e9a92fSRobert Love {
1270*42e9a92fSRobert Love 	void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
1271*42e9a92fSRobert Love 	void *ex_resp_arg;
1272*42e9a92fSRobert Love 	struct fc_frame_header *fh;
1273*42e9a92fSRobert Love 	struct fc_ba_acc *ap;
1274*42e9a92fSRobert Love 	struct fc_seq *sp;
1275*42e9a92fSRobert Love 	u16 low;
1276*42e9a92fSRobert Love 	u16 high;
1277*42e9a92fSRobert Love 	int rc = 1, has_rec = 0;
1278*42e9a92fSRobert Love 
1279*42e9a92fSRobert Love 	fh = fc_frame_header_get(fp);
1280*42e9a92fSRobert Love 	FC_DEBUG_EXCH("exch: BLS rctl %x - %s\n",
1281*42e9a92fSRobert Love 		      fh->fh_r_ctl, fc_exch_rctl_name(fh->fh_r_ctl));
1282*42e9a92fSRobert Love 
1283*42e9a92fSRobert Love 	if (cancel_delayed_work_sync(&ep->timeout_work))
1284*42e9a92fSRobert Love 		fc_exch_release(ep);	/* release from pending timer hold */
1285*42e9a92fSRobert Love 
1286*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
1287*42e9a92fSRobert Love 	switch (fh->fh_r_ctl) {
1288*42e9a92fSRobert Love 	case FC_RCTL_BA_ACC:
1289*42e9a92fSRobert Love 		ap = fc_frame_payload_get(fp, sizeof(*ap));
1290*42e9a92fSRobert Love 		if (!ap)
1291*42e9a92fSRobert Love 			break;
1292*42e9a92fSRobert Love 
1293*42e9a92fSRobert Love 		/*
1294*42e9a92fSRobert Love 		 * Decide whether to establish a Recovery Qualifier.
1295*42e9a92fSRobert Love 		 * We do this if there is a non-empty SEQ_CNT range and
1296*42e9a92fSRobert Love 		 * SEQ_ID is the same as the one we aborted.
1297*42e9a92fSRobert Love 		 */
1298*42e9a92fSRobert Love 		low = ntohs(ap->ba_low_seq_cnt);
1299*42e9a92fSRobert Love 		high = ntohs(ap->ba_high_seq_cnt);
1300*42e9a92fSRobert Love 		if ((ep->esb_stat & ESB_ST_REC_QUAL) == 0 &&
1301*42e9a92fSRobert Love 		    (ap->ba_seq_id_val != FC_BA_SEQ_ID_VAL ||
1302*42e9a92fSRobert Love 		     ap->ba_seq_id == ep->seq_id) && low != high) {
1303*42e9a92fSRobert Love 			ep->esb_stat |= ESB_ST_REC_QUAL;
1304*42e9a92fSRobert Love 			fc_exch_hold(ep);  /* hold for recovery qualifier */
1305*42e9a92fSRobert Love 			has_rec = 1;
1306*42e9a92fSRobert Love 		}
1307*42e9a92fSRobert Love 		break;
1308*42e9a92fSRobert Love 	case FC_RCTL_BA_RJT:
1309*42e9a92fSRobert Love 		break;
1310*42e9a92fSRobert Love 	default:
1311*42e9a92fSRobert Love 		break;
1312*42e9a92fSRobert Love 	}
1313*42e9a92fSRobert Love 
1314*42e9a92fSRobert Love 	resp = ep->resp;
1315*42e9a92fSRobert Love 	ex_resp_arg = ep->arg;
1316*42e9a92fSRobert Love 
1317*42e9a92fSRobert Love 	/* do we need to do some other checks here. Can we reuse more of
1318*42e9a92fSRobert Love 	 * fc_exch_recv_seq_resp
1319*42e9a92fSRobert Love 	 */
1320*42e9a92fSRobert Love 	sp = &ep->seq;
1321*42e9a92fSRobert Love 	/*
1322*42e9a92fSRobert Love 	 * do we want to check END_SEQ as well as LAST_SEQ here?
1323*42e9a92fSRobert Love 	 */
1324*42e9a92fSRobert Love 	if (ep->fh_type != FC_TYPE_FCP &&
1325*42e9a92fSRobert Love 	    ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ)
1326*42e9a92fSRobert Love 		rc = fc_exch_done_locked(ep);
1327*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1328*42e9a92fSRobert Love 	if (!rc)
1329*42e9a92fSRobert Love 		fc_exch_mgr_delete_ep(ep);
1330*42e9a92fSRobert Love 
1331*42e9a92fSRobert Love 	if (resp)
1332*42e9a92fSRobert Love 		resp(sp, fp, ex_resp_arg);
1333*42e9a92fSRobert Love 	else
1334*42e9a92fSRobert Love 		fc_frame_free(fp);
1335*42e9a92fSRobert Love 
1336*42e9a92fSRobert Love 	if (has_rec)
1337*42e9a92fSRobert Love 		fc_exch_timer_set(ep, ep->r_a_tov);
1338*42e9a92fSRobert Love 
1339*42e9a92fSRobert Love }
1340*42e9a92fSRobert Love 
1341*42e9a92fSRobert Love /*
1342*42e9a92fSRobert Love  * Receive BLS sequence.
1343*42e9a92fSRobert Love  * This is always a sequence initiated by the remote side.
1344*42e9a92fSRobert Love  * We may be either the originator or recipient of the exchange.
1345*42e9a92fSRobert Love  */
1346*42e9a92fSRobert Love static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
1347*42e9a92fSRobert Love {
1348*42e9a92fSRobert Love 	struct fc_frame_header *fh;
1349*42e9a92fSRobert Love 	struct fc_exch *ep;
1350*42e9a92fSRobert Love 	u32 f_ctl;
1351*42e9a92fSRobert Love 
1352*42e9a92fSRobert Love 	fh = fc_frame_header_get(fp);
1353*42e9a92fSRobert Love 	f_ctl = ntoh24(fh->fh_f_ctl);
1354*42e9a92fSRobert Love 	fr_seq(fp) = NULL;
1355*42e9a92fSRobert Love 
1356*42e9a92fSRobert Love 	ep = fc_exch_find(mp, (f_ctl & FC_FC_EX_CTX) ?
1357*42e9a92fSRobert Love 			  ntohs(fh->fh_ox_id) : ntohs(fh->fh_rx_id));
1358*42e9a92fSRobert Love 	if (ep && (f_ctl & FC_FC_SEQ_INIT)) {
1359*42e9a92fSRobert Love 		spin_lock_bh(&ep->ex_lock);
1360*42e9a92fSRobert Love 		ep->esb_stat |= ESB_ST_SEQ_INIT;
1361*42e9a92fSRobert Love 		spin_unlock_bh(&ep->ex_lock);
1362*42e9a92fSRobert Love 	}
1363*42e9a92fSRobert Love 	if (f_ctl & FC_FC_SEQ_CTX) {
1364*42e9a92fSRobert Love 		/*
1365*42e9a92fSRobert Love 		 * A response to a sequence we initiated.
1366*42e9a92fSRobert Love 		 * This should only be ACKs for class 2 or F.
1367*42e9a92fSRobert Love 		 */
1368*42e9a92fSRobert Love 		switch (fh->fh_r_ctl) {
1369*42e9a92fSRobert Love 		case FC_RCTL_ACK_1:
1370*42e9a92fSRobert Love 		case FC_RCTL_ACK_0:
1371*42e9a92fSRobert Love 			break;
1372*42e9a92fSRobert Love 		default:
1373*42e9a92fSRobert Love 			FC_DEBUG_EXCH("BLS rctl %x - %s received",
1374*42e9a92fSRobert Love 				      fh->fh_r_ctl,
1375*42e9a92fSRobert Love 				      fc_exch_rctl_name(fh->fh_r_ctl));
1376*42e9a92fSRobert Love 			break;
1377*42e9a92fSRobert Love 		}
1378*42e9a92fSRobert Love 		fc_frame_free(fp);
1379*42e9a92fSRobert Love 	} else {
1380*42e9a92fSRobert Love 		switch (fh->fh_r_ctl) {
1381*42e9a92fSRobert Love 		case FC_RCTL_BA_RJT:
1382*42e9a92fSRobert Love 		case FC_RCTL_BA_ACC:
1383*42e9a92fSRobert Love 			if (ep)
1384*42e9a92fSRobert Love 				fc_exch_abts_resp(ep, fp);
1385*42e9a92fSRobert Love 			else
1386*42e9a92fSRobert Love 				fc_frame_free(fp);
1387*42e9a92fSRobert Love 			break;
1388*42e9a92fSRobert Love 		case FC_RCTL_BA_ABTS:
1389*42e9a92fSRobert Love 			fc_exch_recv_abts(ep, fp);
1390*42e9a92fSRobert Love 			break;
1391*42e9a92fSRobert Love 		default:			/* ignore junk */
1392*42e9a92fSRobert Love 			fc_frame_free(fp);
1393*42e9a92fSRobert Love 			break;
1394*42e9a92fSRobert Love 		}
1395*42e9a92fSRobert Love 	}
1396*42e9a92fSRobert Love 	if (ep)
1397*42e9a92fSRobert Love 		fc_exch_release(ep);	/* release hold taken by fc_exch_find */
1398*42e9a92fSRobert Love }
1399*42e9a92fSRobert Love 
1400*42e9a92fSRobert Love /*
1401*42e9a92fSRobert Love  * Accept sequence with LS_ACC.
1402*42e9a92fSRobert Love  * If this fails due to allocation or transmit congestion, assume the
1403*42e9a92fSRobert Love  * originator will repeat the sequence.
1404*42e9a92fSRobert Love  */
1405*42e9a92fSRobert Love static void fc_seq_ls_acc(struct fc_seq *req_sp)
1406*42e9a92fSRobert Love {
1407*42e9a92fSRobert Love 	struct fc_seq *sp;
1408*42e9a92fSRobert Love 	struct fc_els_ls_acc *acc;
1409*42e9a92fSRobert Love 	struct fc_frame *fp;
1410*42e9a92fSRobert Love 
1411*42e9a92fSRobert Love 	sp = fc_seq_start_next(req_sp);
1412*42e9a92fSRobert Love 	fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc));
1413*42e9a92fSRobert Love 	if (fp) {
1414*42e9a92fSRobert Love 		acc = fc_frame_payload_get(fp, sizeof(*acc));
1415*42e9a92fSRobert Love 		memset(acc, 0, sizeof(*acc));
1416*42e9a92fSRobert Love 		acc->la_cmd = ELS_LS_ACC;
1417*42e9a92fSRobert Love 		fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
1418*42e9a92fSRobert Love 	}
1419*42e9a92fSRobert Love }
1420*42e9a92fSRobert Love 
1421*42e9a92fSRobert Love /*
1422*42e9a92fSRobert Love  * Reject sequence with ELS LS_RJT.
1423*42e9a92fSRobert Love  * If this fails due to allocation or transmit congestion, assume the
1424*42e9a92fSRobert Love  * originator will repeat the sequence.
1425*42e9a92fSRobert Love  */
1426*42e9a92fSRobert Love static void fc_seq_ls_rjt(struct fc_seq *req_sp, enum fc_els_rjt_reason reason,
1427*42e9a92fSRobert Love 			  enum fc_els_rjt_explan explan)
1428*42e9a92fSRobert Love {
1429*42e9a92fSRobert Love 	struct fc_seq *sp;
1430*42e9a92fSRobert Love 	struct fc_els_ls_rjt *rjt;
1431*42e9a92fSRobert Love 	struct fc_frame *fp;
1432*42e9a92fSRobert Love 
1433*42e9a92fSRobert Love 	sp = fc_seq_start_next(req_sp);
1434*42e9a92fSRobert Love 	fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*rjt));
1435*42e9a92fSRobert Love 	if (fp) {
1436*42e9a92fSRobert Love 		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
1437*42e9a92fSRobert Love 		memset(rjt, 0, sizeof(*rjt));
1438*42e9a92fSRobert Love 		rjt->er_cmd = ELS_LS_RJT;
1439*42e9a92fSRobert Love 		rjt->er_reason = reason;
1440*42e9a92fSRobert Love 		rjt->er_explan = explan;
1441*42e9a92fSRobert Love 		fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
1442*42e9a92fSRobert Love 	}
1443*42e9a92fSRobert Love }
1444*42e9a92fSRobert Love 
1445*42e9a92fSRobert Love static void fc_exch_reset(struct fc_exch *ep)
1446*42e9a92fSRobert Love {
1447*42e9a92fSRobert Love 	struct fc_seq *sp;
1448*42e9a92fSRobert Love 	void (*resp)(struct fc_seq *, struct fc_frame *, void *);
1449*42e9a92fSRobert Love 	void *arg;
1450*42e9a92fSRobert Love 	int rc = 1;
1451*42e9a92fSRobert Love 
1452*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
1453*42e9a92fSRobert Love 	ep->state |= FC_EX_RST_CLEANUP;
1454*42e9a92fSRobert Love 	/*
1455*42e9a92fSRobert Love 	 * we really want to call del_timer_sync, but cannot due
1456*42e9a92fSRobert Love 	 * to the lport calling with the lport lock held (some resp
1457*42e9a92fSRobert Love 	 * functions can also grab the lport lock which could cause
1458*42e9a92fSRobert Love 	 * a deadlock).
1459*42e9a92fSRobert Love 	 */
1460*42e9a92fSRobert Love 	if (cancel_delayed_work(&ep->timeout_work))
1461*42e9a92fSRobert Love 		atomic_dec(&ep->ex_refcnt);	/* drop hold for timer */
1462*42e9a92fSRobert Love 	resp = ep->resp;
1463*42e9a92fSRobert Love 	ep->resp = NULL;
1464*42e9a92fSRobert Love 	if (ep->esb_stat & ESB_ST_REC_QUAL)
1465*42e9a92fSRobert Love 		atomic_dec(&ep->ex_refcnt);	/* drop hold for rec_qual */
1466*42e9a92fSRobert Love 	ep->esb_stat &= ~ESB_ST_REC_QUAL;
1467*42e9a92fSRobert Love 	arg = ep->arg;
1468*42e9a92fSRobert Love 	sp = &ep->seq;
1469*42e9a92fSRobert Love 	rc = fc_exch_done_locked(ep);
1470*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1471*42e9a92fSRobert Love 	if (!rc)
1472*42e9a92fSRobert Love 		fc_exch_mgr_delete_ep(ep);
1473*42e9a92fSRobert Love 
1474*42e9a92fSRobert Love 	if (resp)
1475*42e9a92fSRobert Love 		resp(sp, ERR_PTR(-FC_EX_CLOSED), arg);
1476*42e9a92fSRobert Love }
1477*42e9a92fSRobert Love 
1478*42e9a92fSRobert Love /*
1479*42e9a92fSRobert Love  * Reset an exchange manager, releasing all sequences and exchanges.
1480*42e9a92fSRobert Love  * If sid is non-zero, reset only exchanges we source from that FID.
1481*42e9a92fSRobert Love  * If did is non-zero, reset only exchanges destined to that FID.
1482*42e9a92fSRobert Love  */
1483*42e9a92fSRobert Love void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, u32 did)
1484*42e9a92fSRobert Love {
1485*42e9a92fSRobert Love 	struct fc_exch *ep;
1486*42e9a92fSRobert Love 	struct fc_exch *next;
1487*42e9a92fSRobert Love 
1488*42e9a92fSRobert Love 	spin_lock_bh(&mp->em_lock);
1489*42e9a92fSRobert Love restart:
1490*42e9a92fSRobert Love 	list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
1491*42e9a92fSRobert Love 		if ((sid == 0 || sid == ep->sid) &&
1492*42e9a92fSRobert Love 		    (did == 0 || did == ep->did)) {
1493*42e9a92fSRobert Love 			fc_exch_hold(ep);
1494*42e9a92fSRobert Love 			spin_unlock_bh(&mp->em_lock);
1495*42e9a92fSRobert Love 
1496*42e9a92fSRobert Love 			fc_exch_reset(ep);
1497*42e9a92fSRobert Love 
1498*42e9a92fSRobert Love 			fc_exch_release(ep);
1499*42e9a92fSRobert Love 			spin_lock_bh(&mp->em_lock);
1500*42e9a92fSRobert Love 
1501*42e9a92fSRobert Love 			/*
1502*42e9a92fSRobert Love 			 * must restart loop incase while lock was down
1503*42e9a92fSRobert Love 			 * multiple eps were released.
1504*42e9a92fSRobert Love 			 */
1505*42e9a92fSRobert Love 			goto restart;
1506*42e9a92fSRobert Love 		}
1507*42e9a92fSRobert Love 	}
1508*42e9a92fSRobert Love 	spin_unlock_bh(&mp->em_lock);
1509*42e9a92fSRobert Love }
1510*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_mgr_reset);
1511*42e9a92fSRobert Love 
1512*42e9a92fSRobert Love /*
1513*42e9a92fSRobert Love  * Handle incoming ELS REC - Read Exchange Concise.
1514*42e9a92fSRobert Love  * Note that the requesting port may be different than the S_ID in the request.
1515*42e9a92fSRobert Love  */
1516*42e9a92fSRobert Love static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
1517*42e9a92fSRobert Love {
1518*42e9a92fSRobert Love 	struct fc_frame *fp;
1519*42e9a92fSRobert Love 	struct fc_exch *ep;
1520*42e9a92fSRobert Love 	struct fc_exch_mgr *em;
1521*42e9a92fSRobert Love 	struct fc_els_rec *rp;
1522*42e9a92fSRobert Love 	struct fc_els_rec_acc *acc;
1523*42e9a92fSRobert Love 	enum fc_els_rjt_reason reason = ELS_RJT_LOGIC;
1524*42e9a92fSRobert Love 	enum fc_els_rjt_explan explan;
1525*42e9a92fSRobert Love 	u32 sid;
1526*42e9a92fSRobert Love 	u16 rxid;
1527*42e9a92fSRobert Love 	u16 oxid;
1528*42e9a92fSRobert Love 
1529*42e9a92fSRobert Love 	rp = fc_frame_payload_get(rfp, sizeof(*rp));
1530*42e9a92fSRobert Love 	explan = ELS_EXPL_INV_LEN;
1531*42e9a92fSRobert Love 	if (!rp)
1532*42e9a92fSRobert Love 		goto reject;
1533*42e9a92fSRobert Love 	sid = ntoh24(rp->rec_s_id);
1534*42e9a92fSRobert Love 	rxid = ntohs(rp->rec_rx_id);
1535*42e9a92fSRobert Love 	oxid = ntohs(rp->rec_ox_id);
1536*42e9a92fSRobert Love 
1537*42e9a92fSRobert Love 	/*
1538*42e9a92fSRobert Love 	 * Currently it's hard to find the local S_ID from the exchange
1539*42e9a92fSRobert Love 	 * manager.  This will eventually be fixed, but for now it's easier
1540*42e9a92fSRobert Love 	 * to lookup the subject exchange twice, once as if we were
1541*42e9a92fSRobert Love 	 * the initiator, and then again if we weren't.
1542*42e9a92fSRobert Love 	 */
1543*42e9a92fSRobert Love 	em = fc_seq_exch(sp)->em;
1544*42e9a92fSRobert Love 	ep = fc_exch_find(em, oxid);
1545*42e9a92fSRobert Love 	explan = ELS_EXPL_OXID_RXID;
1546*42e9a92fSRobert Love 	if (ep && ep->oid == sid) {
1547*42e9a92fSRobert Love 		if (ep->rxid != FC_XID_UNKNOWN &&
1548*42e9a92fSRobert Love 		    rxid != FC_XID_UNKNOWN &&
1549*42e9a92fSRobert Love 		    ep->rxid != rxid)
1550*42e9a92fSRobert Love 			goto rel;
1551*42e9a92fSRobert Love 	} else {
1552*42e9a92fSRobert Love 		if (ep)
1553*42e9a92fSRobert Love 			fc_exch_release(ep);
1554*42e9a92fSRobert Love 		ep = NULL;
1555*42e9a92fSRobert Love 		if (rxid != FC_XID_UNKNOWN)
1556*42e9a92fSRobert Love 			ep = fc_exch_find(em, rxid);
1557*42e9a92fSRobert Love 		if (!ep)
1558*42e9a92fSRobert Love 			goto reject;
1559*42e9a92fSRobert Love 	}
1560*42e9a92fSRobert Love 
1561*42e9a92fSRobert Love 	fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc));
1562*42e9a92fSRobert Love 	if (!fp) {
1563*42e9a92fSRobert Love 		fc_exch_done(sp);
1564*42e9a92fSRobert Love 		goto out;
1565*42e9a92fSRobert Love 	}
1566*42e9a92fSRobert Love 	sp = fc_seq_start_next(sp);
1567*42e9a92fSRobert Love 	acc = fc_frame_payload_get(fp, sizeof(*acc));
1568*42e9a92fSRobert Love 	memset(acc, 0, sizeof(*acc));
1569*42e9a92fSRobert Love 	acc->reca_cmd = ELS_LS_ACC;
1570*42e9a92fSRobert Love 	acc->reca_ox_id = rp->rec_ox_id;
1571*42e9a92fSRobert Love 	memcpy(acc->reca_ofid, rp->rec_s_id, 3);
1572*42e9a92fSRobert Love 	acc->reca_rx_id = htons(ep->rxid);
1573*42e9a92fSRobert Love 	if (ep->sid == ep->oid)
1574*42e9a92fSRobert Love 		hton24(acc->reca_rfid, ep->did);
1575*42e9a92fSRobert Love 	else
1576*42e9a92fSRobert Love 		hton24(acc->reca_rfid, ep->sid);
1577*42e9a92fSRobert Love 	acc->reca_fc4value = htonl(ep->seq.rec_data);
1578*42e9a92fSRobert Love 	acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP |
1579*42e9a92fSRobert Love 						 ESB_ST_SEQ_INIT |
1580*42e9a92fSRobert Love 						 ESB_ST_COMPLETE));
1581*42e9a92fSRobert Love 	sp = fc_seq_start_next(sp);
1582*42e9a92fSRobert Love 	fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS);
1583*42e9a92fSRobert Love out:
1584*42e9a92fSRobert Love 	fc_exch_release(ep);
1585*42e9a92fSRobert Love 	fc_frame_free(rfp);
1586*42e9a92fSRobert Love 	return;
1587*42e9a92fSRobert Love 
1588*42e9a92fSRobert Love rel:
1589*42e9a92fSRobert Love 	fc_exch_release(ep);
1590*42e9a92fSRobert Love reject:
1591*42e9a92fSRobert Love 	fc_seq_ls_rjt(sp, reason, explan);
1592*42e9a92fSRobert Love 	fc_frame_free(rfp);
1593*42e9a92fSRobert Love }
1594*42e9a92fSRobert Love 
1595*42e9a92fSRobert Love /*
1596*42e9a92fSRobert Love  * Handle response from RRQ.
1597*42e9a92fSRobert Love  * Not much to do here, really.
1598*42e9a92fSRobert Love  * Should report errors.
1599*42e9a92fSRobert Love  *
1600*42e9a92fSRobert Love  * TODO: fix error handler.
1601*42e9a92fSRobert Love  */
1602*42e9a92fSRobert Love static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
1603*42e9a92fSRobert Love {
1604*42e9a92fSRobert Love 	struct fc_exch *aborted_ep = arg;
1605*42e9a92fSRobert Love 	unsigned int op;
1606*42e9a92fSRobert Love 
1607*42e9a92fSRobert Love 	if (IS_ERR(fp)) {
1608*42e9a92fSRobert Love 		int err = PTR_ERR(fp);
1609*42e9a92fSRobert Love 
1610*42e9a92fSRobert Love 		if (err == -FC_EX_CLOSED)
1611*42e9a92fSRobert Love 			goto cleanup;
1612*42e9a92fSRobert Love 		FC_DBG("Cannot process RRQ, because of frame error %d\n", err);
1613*42e9a92fSRobert Love 		return;
1614*42e9a92fSRobert Love 	}
1615*42e9a92fSRobert Love 
1616*42e9a92fSRobert Love 	op = fc_frame_payload_op(fp);
1617*42e9a92fSRobert Love 	fc_frame_free(fp);
1618*42e9a92fSRobert Love 
1619*42e9a92fSRobert Love 	switch (op) {
1620*42e9a92fSRobert Love 	case ELS_LS_RJT:
1621*42e9a92fSRobert Love 		FC_DBG("LS_RJT for RRQ");
1622*42e9a92fSRobert Love 		/* fall through */
1623*42e9a92fSRobert Love 	case ELS_LS_ACC:
1624*42e9a92fSRobert Love 		goto cleanup;
1625*42e9a92fSRobert Love 	default:
1626*42e9a92fSRobert Love 		FC_DBG("unexpected response op %x for RRQ", op);
1627*42e9a92fSRobert Love 		return;
1628*42e9a92fSRobert Love 	}
1629*42e9a92fSRobert Love 
1630*42e9a92fSRobert Love cleanup:
1631*42e9a92fSRobert Love 	fc_exch_done(&aborted_ep->seq);
1632*42e9a92fSRobert Love 	/* drop hold for rec qual */
1633*42e9a92fSRobert Love 	fc_exch_release(aborted_ep);
1634*42e9a92fSRobert Love }
1635*42e9a92fSRobert Love 
1636*42e9a92fSRobert Love /*
1637*42e9a92fSRobert Love  * Send ELS RRQ - Reinstate Recovery Qualifier.
1638*42e9a92fSRobert Love  * This tells the remote port to stop blocking the use of
1639*42e9a92fSRobert Love  * the exchange and the seq_cnt range.
1640*42e9a92fSRobert Love  */
1641*42e9a92fSRobert Love static void fc_exch_rrq(struct fc_exch *ep)
1642*42e9a92fSRobert Love {
1643*42e9a92fSRobert Love 	struct fc_lport *lp;
1644*42e9a92fSRobert Love 	struct fc_els_rrq *rrq;
1645*42e9a92fSRobert Love 	struct fc_frame *fp;
1646*42e9a92fSRobert Love 	struct fc_seq *rrq_sp;
1647*42e9a92fSRobert Love 	u32 did;
1648*42e9a92fSRobert Love 
1649*42e9a92fSRobert Love 	lp = ep->lp;
1650*42e9a92fSRobert Love 
1651*42e9a92fSRobert Love 	fp = fc_frame_alloc(lp, sizeof(*rrq));
1652*42e9a92fSRobert Love 	if (!fp)
1653*42e9a92fSRobert Love 		return;
1654*42e9a92fSRobert Love 	rrq = fc_frame_payload_get(fp, sizeof(*rrq));
1655*42e9a92fSRobert Love 	memset(rrq, 0, sizeof(*rrq));
1656*42e9a92fSRobert Love 	rrq->rrq_cmd = ELS_RRQ;
1657*42e9a92fSRobert Love 	hton24(rrq->rrq_s_id, ep->sid);
1658*42e9a92fSRobert Love 	rrq->rrq_ox_id = htons(ep->oxid);
1659*42e9a92fSRobert Love 	rrq->rrq_rx_id = htons(ep->rxid);
1660*42e9a92fSRobert Love 
1661*42e9a92fSRobert Love 	did = ep->did;
1662*42e9a92fSRobert Love 	if (ep->esb_stat & ESB_ST_RESP)
1663*42e9a92fSRobert Love 		did = ep->sid;
1664*42e9a92fSRobert Love 
1665*42e9a92fSRobert Love 	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did,
1666*42e9a92fSRobert Love 		       fc_host_port_id(lp->host), FC_TYPE_ELS,
1667*42e9a92fSRobert Love 		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
1668*42e9a92fSRobert Love 
1669*42e9a92fSRobert Love 	rrq_sp = fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep,
1670*42e9a92fSRobert Love 				  lp->e_d_tov);
1671*42e9a92fSRobert Love 	if (!rrq_sp) {
1672*42e9a92fSRobert Love 		ep->esb_stat |= ESB_ST_REC_QUAL;
1673*42e9a92fSRobert Love 		fc_exch_timer_set_locked(ep, ep->r_a_tov);
1674*42e9a92fSRobert Love 		return;
1675*42e9a92fSRobert Love 	}
1676*42e9a92fSRobert Love }
1677*42e9a92fSRobert Love 
1678*42e9a92fSRobert Love 
1679*42e9a92fSRobert Love /*
1680*42e9a92fSRobert Love  * Handle incoming ELS RRQ - Reset Recovery Qualifier.
1681*42e9a92fSRobert Love  */
1682*42e9a92fSRobert Love static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp)
1683*42e9a92fSRobert Love {
1684*42e9a92fSRobert Love 	struct fc_exch *ep;		/* request or subject exchange */
1685*42e9a92fSRobert Love 	struct fc_els_rrq *rp;
1686*42e9a92fSRobert Love 	u32 sid;
1687*42e9a92fSRobert Love 	u16 xid;
1688*42e9a92fSRobert Love 	enum fc_els_rjt_explan explan;
1689*42e9a92fSRobert Love 
1690*42e9a92fSRobert Love 	rp = fc_frame_payload_get(fp, sizeof(*rp));
1691*42e9a92fSRobert Love 	explan = ELS_EXPL_INV_LEN;
1692*42e9a92fSRobert Love 	if (!rp)
1693*42e9a92fSRobert Love 		goto reject;
1694*42e9a92fSRobert Love 
1695*42e9a92fSRobert Love 	/*
1696*42e9a92fSRobert Love 	 * lookup subject exchange.
1697*42e9a92fSRobert Love 	 */
1698*42e9a92fSRobert Love 	ep = fc_seq_exch(sp);
1699*42e9a92fSRobert Love 	sid = ntoh24(rp->rrq_s_id);		/* subject source */
1700*42e9a92fSRobert Love 	xid = ep->did == sid ? ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id);
1701*42e9a92fSRobert Love 	ep = fc_exch_find(ep->em, xid);
1702*42e9a92fSRobert Love 
1703*42e9a92fSRobert Love 	explan = ELS_EXPL_OXID_RXID;
1704*42e9a92fSRobert Love 	if (!ep)
1705*42e9a92fSRobert Love 		goto reject;
1706*42e9a92fSRobert Love 	spin_lock_bh(&ep->ex_lock);
1707*42e9a92fSRobert Love 	if (ep->oxid != ntohs(rp->rrq_ox_id))
1708*42e9a92fSRobert Love 		goto unlock_reject;
1709*42e9a92fSRobert Love 	if (ep->rxid != ntohs(rp->rrq_rx_id) &&
1710*42e9a92fSRobert Love 	    ep->rxid != FC_XID_UNKNOWN)
1711*42e9a92fSRobert Love 		goto unlock_reject;
1712*42e9a92fSRobert Love 	explan = ELS_EXPL_SID;
1713*42e9a92fSRobert Love 	if (ep->sid != sid)
1714*42e9a92fSRobert Love 		goto unlock_reject;
1715*42e9a92fSRobert Love 
1716*42e9a92fSRobert Love 	/*
1717*42e9a92fSRobert Love 	 * Clear Recovery Qualifier state, and cancel timer if complete.
1718*42e9a92fSRobert Love 	 */
1719*42e9a92fSRobert Love 	if (ep->esb_stat & ESB_ST_REC_QUAL) {
1720*42e9a92fSRobert Love 		ep->esb_stat &= ~ESB_ST_REC_QUAL;
1721*42e9a92fSRobert Love 		atomic_dec(&ep->ex_refcnt);	/* drop hold for rec qual */
1722*42e9a92fSRobert Love 	}
1723*42e9a92fSRobert Love 	if (ep->esb_stat & ESB_ST_COMPLETE) {
1724*42e9a92fSRobert Love 		if (cancel_delayed_work(&ep->timeout_work))
1725*42e9a92fSRobert Love 			atomic_dec(&ep->ex_refcnt);	/* drop timer hold */
1726*42e9a92fSRobert Love 	}
1727*42e9a92fSRobert Love 
1728*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1729*42e9a92fSRobert Love 
1730*42e9a92fSRobert Love 	/*
1731*42e9a92fSRobert Love 	 * Send LS_ACC.
1732*42e9a92fSRobert Love 	 */
1733*42e9a92fSRobert Love 	fc_seq_ls_acc(sp);
1734*42e9a92fSRobert Love 	fc_frame_free(fp);
1735*42e9a92fSRobert Love 	return;
1736*42e9a92fSRobert Love 
1737*42e9a92fSRobert Love unlock_reject:
1738*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1739*42e9a92fSRobert Love 	fc_exch_release(ep);	/* drop hold from fc_exch_find */
1740*42e9a92fSRobert Love reject:
1741*42e9a92fSRobert Love 	fc_seq_ls_rjt(sp, ELS_RJT_LOGIC, explan);
1742*42e9a92fSRobert Love 	fc_frame_free(fp);
1743*42e9a92fSRobert Love }
1744*42e9a92fSRobert Love 
1745*42e9a92fSRobert Love struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp,
1746*42e9a92fSRobert Love 				      enum fc_class class,
1747*42e9a92fSRobert Love 				      u16 min_xid, u16 max_xid)
1748*42e9a92fSRobert Love {
1749*42e9a92fSRobert Love 	struct fc_exch_mgr *mp;
1750*42e9a92fSRobert Love 	size_t len;
1751*42e9a92fSRobert Love 
1752*42e9a92fSRobert Love 	if (max_xid <= min_xid || min_xid == 0 || max_xid == FC_XID_UNKNOWN) {
1753*42e9a92fSRobert Love 		FC_DBG("Invalid min_xid 0x:%x and max_xid 0x:%x\n",
1754*42e9a92fSRobert Love 		       min_xid, max_xid);
1755*42e9a92fSRobert Love 		return NULL;
1756*42e9a92fSRobert Love 	}
1757*42e9a92fSRobert Love 
1758*42e9a92fSRobert Love 	/*
1759*42e9a92fSRobert Love 	 * Memory need for EM
1760*42e9a92fSRobert Love 	 */
1761*42e9a92fSRobert Love #define xid_ok(i, m1, m2) (((i) >= (m1)) && ((i) <= (m2)))
1762*42e9a92fSRobert Love 	len = (max_xid - min_xid + 1) * (sizeof(struct fc_exch *));
1763*42e9a92fSRobert Love 	len += sizeof(struct fc_exch_mgr);
1764*42e9a92fSRobert Love 
1765*42e9a92fSRobert Love 	mp = kzalloc(len, GFP_ATOMIC);
1766*42e9a92fSRobert Love 	if (!mp)
1767*42e9a92fSRobert Love 		return NULL;
1768*42e9a92fSRobert Love 
1769*42e9a92fSRobert Love 	mp->class = class;
1770*42e9a92fSRobert Love 	mp->total_exches = 0;
1771*42e9a92fSRobert Love 	mp->exches = (struct fc_exch **)(mp + 1);
1772*42e9a92fSRobert Love 	mp->lp = lp;
1773*42e9a92fSRobert Love 	/* adjust em exch xid range for offload */
1774*42e9a92fSRobert Love 	mp->min_xid = min_xid;
1775*42e9a92fSRobert Love 	mp->max_xid = max_xid;
1776*42e9a92fSRobert Love 	mp->last_xid = min_xid - 1;
1777*42e9a92fSRobert Love 	mp->max_read = 0;
1778*42e9a92fSRobert Love 	mp->last_read = 0;
1779*42e9a92fSRobert Love 	if (lp->lro_enabled && xid_ok(lp->lro_xid, min_xid, max_xid)) {
1780*42e9a92fSRobert Love 		mp->max_read = lp->lro_xid;
1781*42e9a92fSRobert Love 		mp->last_read = min_xid - 1;
1782*42e9a92fSRobert Love 		mp->last_xid = mp->max_read;
1783*42e9a92fSRobert Love 	} else {
1784*42e9a92fSRobert Love 		/* disable lro if no xid control over read */
1785*42e9a92fSRobert Love 		lp->lro_enabled = 0;
1786*42e9a92fSRobert Love 	}
1787*42e9a92fSRobert Love 
1788*42e9a92fSRobert Love 	INIT_LIST_HEAD(&mp->ex_list);
1789*42e9a92fSRobert Love 	spin_lock_init(&mp->em_lock);
1790*42e9a92fSRobert Love 
1791*42e9a92fSRobert Love 	mp->ep_pool = mempool_create_slab_pool(2, fc_em_cachep);
1792*42e9a92fSRobert Love 	if (!mp->ep_pool)
1793*42e9a92fSRobert Love 		goto free_mp;
1794*42e9a92fSRobert Love 
1795*42e9a92fSRobert Love 	return mp;
1796*42e9a92fSRobert Love 
1797*42e9a92fSRobert Love free_mp:
1798*42e9a92fSRobert Love 	kfree(mp);
1799*42e9a92fSRobert Love 	return NULL;
1800*42e9a92fSRobert Love }
1801*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_mgr_alloc);
1802*42e9a92fSRobert Love 
1803*42e9a92fSRobert Love void fc_exch_mgr_free(struct fc_exch_mgr *mp)
1804*42e9a92fSRobert Love {
1805*42e9a92fSRobert Love 	WARN_ON(!mp);
1806*42e9a92fSRobert Love 	/*
1807*42e9a92fSRobert Love 	 * The total exch count must be zero
1808*42e9a92fSRobert Love 	 * before freeing exchange manager.
1809*42e9a92fSRobert Love 	 */
1810*42e9a92fSRobert Love 	WARN_ON(mp->total_exches != 0);
1811*42e9a92fSRobert Love 	mempool_destroy(mp->ep_pool);
1812*42e9a92fSRobert Love 	kfree(mp);
1813*42e9a92fSRobert Love }
1814*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_mgr_free);
1815*42e9a92fSRobert Love 
1816*42e9a92fSRobert Love struct fc_exch *fc_exch_get(struct fc_lport *lp, struct fc_frame *fp)
1817*42e9a92fSRobert Love {
1818*42e9a92fSRobert Love 	if (!lp || !lp->emp)
1819*42e9a92fSRobert Love 		return NULL;
1820*42e9a92fSRobert Love 
1821*42e9a92fSRobert Love 	return fc_exch_alloc(lp->emp, fp, 0);
1822*42e9a92fSRobert Love }
1823*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_get);
1824*42e9a92fSRobert Love 
1825*42e9a92fSRobert Love struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
1826*42e9a92fSRobert Love 				struct fc_frame *fp,
1827*42e9a92fSRobert Love 				void (*resp)(struct fc_seq *,
1828*42e9a92fSRobert Love 					     struct fc_frame *fp,
1829*42e9a92fSRobert Love 					     void *arg),
1830*42e9a92fSRobert Love 				void (*destructor)(struct fc_seq *, void *),
1831*42e9a92fSRobert Love 				void *arg, u32 timer_msec)
1832*42e9a92fSRobert Love {
1833*42e9a92fSRobert Love 	struct fc_exch *ep;
1834*42e9a92fSRobert Love 	struct fc_seq *sp = NULL;
1835*42e9a92fSRobert Love 	struct fc_frame_header *fh;
1836*42e9a92fSRobert Love 	int rc = 1;
1837*42e9a92fSRobert Love 
1838*42e9a92fSRobert Love 	ep = lp->tt.exch_get(lp, fp);
1839*42e9a92fSRobert Love 	if (!ep) {
1840*42e9a92fSRobert Love 		fc_frame_free(fp);
1841*42e9a92fSRobert Love 		return NULL;
1842*42e9a92fSRobert Love 	}
1843*42e9a92fSRobert Love 	ep->esb_stat |= ESB_ST_SEQ_INIT;
1844*42e9a92fSRobert Love 	fh = fc_frame_header_get(fp);
1845*42e9a92fSRobert Love 	fc_exch_set_addr(ep, ntoh24(fh->fh_s_id), ntoh24(fh->fh_d_id));
1846*42e9a92fSRobert Love 	ep->resp = resp;
1847*42e9a92fSRobert Love 	ep->destructor = destructor;
1848*42e9a92fSRobert Love 	ep->arg = arg;
1849*42e9a92fSRobert Love 	ep->r_a_tov = FC_DEF_R_A_TOV;
1850*42e9a92fSRobert Love 	ep->lp = lp;
1851*42e9a92fSRobert Love 	sp = &ep->seq;
1852*42e9a92fSRobert Love 
1853*42e9a92fSRobert Love 	ep->fh_type = fh->fh_type; /* save for possbile timeout handling */
1854*42e9a92fSRobert Love 	ep->f_ctl = ntoh24(fh->fh_f_ctl);
1855*42e9a92fSRobert Love 	fc_exch_setup_hdr(ep, fp, ep->f_ctl);
1856*42e9a92fSRobert Love 	sp->cnt++;
1857*42e9a92fSRobert Love 
1858*42e9a92fSRobert Love 	if (unlikely(lp->tt.frame_send(lp, fp)))
1859*42e9a92fSRobert Love 		goto err;
1860*42e9a92fSRobert Love 
1861*42e9a92fSRobert Love 	if (timer_msec)
1862*42e9a92fSRobert Love 		fc_exch_timer_set_locked(ep, timer_msec);
1863*42e9a92fSRobert Love 	ep->f_ctl &= ~FC_FC_FIRST_SEQ;	/* not first seq */
1864*42e9a92fSRobert Love 
1865*42e9a92fSRobert Love 	if (ep->f_ctl & FC_FC_SEQ_INIT)
1866*42e9a92fSRobert Love 		ep->esb_stat &= ~ESB_ST_SEQ_INIT;
1867*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1868*42e9a92fSRobert Love 	return sp;
1869*42e9a92fSRobert Love err:
1870*42e9a92fSRobert Love 	rc = fc_exch_done_locked(ep);
1871*42e9a92fSRobert Love 	spin_unlock_bh(&ep->ex_lock);
1872*42e9a92fSRobert Love 	if (!rc)
1873*42e9a92fSRobert Love 		fc_exch_mgr_delete_ep(ep);
1874*42e9a92fSRobert Love 	return NULL;
1875*42e9a92fSRobert Love }
1876*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_seq_send);
1877*42e9a92fSRobert Love 
1878*42e9a92fSRobert Love /*
1879*42e9a92fSRobert Love  * Receive a frame
1880*42e9a92fSRobert Love  */
1881*42e9a92fSRobert Love void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp,
1882*42e9a92fSRobert Love 		  struct fc_frame *fp)
1883*42e9a92fSRobert Love {
1884*42e9a92fSRobert Love 	struct fc_frame_header *fh = fc_frame_header_get(fp);
1885*42e9a92fSRobert Love 	u32 f_ctl;
1886*42e9a92fSRobert Love 
1887*42e9a92fSRobert Love 	/* lport lock ? */
1888*42e9a92fSRobert Love 	if (!lp || !mp || (lp->state == LPORT_ST_NONE)) {
1889*42e9a92fSRobert Love 		FC_DBG("fc_lport or EM is not allocated and configured");
1890*42e9a92fSRobert Love 		fc_frame_free(fp);
1891*42e9a92fSRobert Love 		return;
1892*42e9a92fSRobert Love 	}
1893*42e9a92fSRobert Love 
1894*42e9a92fSRobert Love 	/*
1895*42e9a92fSRobert Love 	 * If frame is marked invalid, just drop it.
1896*42e9a92fSRobert Love 	 */
1897*42e9a92fSRobert Love 	f_ctl = ntoh24(fh->fh_f_ctl);
1898*42e9a92fSRobert Love 	switch (fr_eof(fp)) {
1899*42e9a92fSRobert Love 	case FC_EOF_T:
1900*42e9a92fSRobert Love 		if (f_ctl & FC_FC_END_SEQ)
1901*42e9a92fSRobert Love 			skb_trim(fp_skb(fp), fr_len(fp) - FC_FC_FILL(f_ctl));
1902*42e9a92fSRobert Love 		/* fall through */
1903*42e9a92fSRobert Love 	case FC_EOF_N:
1904*42e9a92fSRobert Love 		if (fh->fh_type == FC_TYPE_BLS)
1905*42e9a92fSRobert Love 			fc_exch_recv_bls(mp, fp);
1906*42e9a92fSRobert Love 		else if ((f_ctl & (FC_FC_EX_CTX | FC_FC_SEQ_CTX)) ==
1907*42e9a92fSRobert Love 			 FC_FC_EX_CTX)
1908*42e9a92fSRobert Love 			fc_exch_recv_seq_resp(mp, fp);
1909*42e9a92fSRobert Love 		else if (f_ctl & FC_FC_SEQ_CTX)
1910*42e9a92fSRobert Love 			fc_exch_recv_resp(mp, fp);
1911*42e9a92fSRobert Love 		else
1912*42e9a92fSRobert Love 			fc_exch_recv_req(lp, mp, fp);
1913*42e9a92fSRobert Love 		break;
1914*42e9a92fSRobert Love 	default:
1915*42e9a92fSRobert Love 		FC_DBG("dropping invalid frame (eof %x)", fr_eof(fp));
1916*42e9a92fSRobert Love 		fc_frame_free(fp);
1917*42e9a92fSRobert Love 		break;
1918*42e9a92fSRobert Love 	}
1919*42e9a92fSRobert Love }
1920*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_recv);
1921*42e9a92fSRobert Love 
1922*42e9a92fSRobert Love int fc_exch_init(struct fc_lport *lp)
1923*42e9a92fSRobert Love {
1924*42e9a92fSRobert Love 	if (!lp->tt.exch_get) {
1925*42e9a92fSRobert Love 		/*
1926*42e9a92fSRobert Love 		 *  exch_put() should be NULL if
1927*42e9a92fSRobert Love 		 *  exch_get() is NULL
1928*42e9a92fSRobert Love 		 */
1929*42e9a92fSRobert Love 		WARN_ON(lp->tt.exch_put);
1930*42e9a92fSRobert Love 		lp->tt.exch_get = fc_exch_get;
1931*42e9a92fSRobert Love 	}
1932*42e9a92fSRobert Love 
1933*42e9a92fSRobert Love 	if (!lp->tt.seq_start_next)
1934*42e9a92fSRobert Love 		lp->tt.seq_start_next = fc_seq_start_next;
1935*42e9a92fSRobert Love 
1936*42e9a92fSRobert Love 	if (!lp->tt.exch_seq_send)
1937*42e9a92fSRobert Love 		lp->tt.exch_seq_send = fc_exch_seq_send;
1938*42e9a92fSRobert Love 
1939*42e9a92fSRobert Love 	if (!lp->tt.seq_send)
1940*42e9a92fSRobert Love 		lp->tt.seq_send = fc_seq_send;
1941*42e9a92fSRobert Love 
1942*42e9a92fSRobert Love 	if (!lp->tt.seq_els_rsp_send)
1943*42e9a92fSRobert Love 		lp->tt.seq_els_rsp_send = fc_seq_els_rsp_send;
1944*42e9a92fSRobert Love 
1945*42e9a92fSRobert Love 	if (!lp->tt.exch_done)
1946*42e9a92fSRobert Love 		lp->tt.exch_done = fc_exch_done;
1947*42e9a92fSRobert Love 
1948*42e9a92fSRobert Love 	if (!lp->tt.exch_mgr_reset)
1949*42e9a92fSRobert Love 		lp->tt.exch_mgr_reset = fc_exch_mgr_reset;
1950*42e9a92fSRobert Love 
1951*42e9a92fSRobert Love 	if (!lp->tt.seq_exch_abort)
1952*42e9a92fSRobert Love 		lp->tt.seq_exch_abort = fc_seq_exch_abort;
1953*42e9a92fSRobert Love 
1954*42e9a92fSRobert Love 	return 0;
1955*42e9a92fSRobert Love }
1956*42e9a92fSRobert Love EXPORT_SYMBOL(fc_exch_init);
1957*42e9a92fSRobert Love 
1958*42e9a92fSRobert Love int fc_setup_exch_mgr(void)
1959*42e9a92fSRobert Love {
1960*42e9a92fSRobert Love 	fc_em_cachep = kmem_cache_create("libfc_em", sizeof(struct fc_exch),
1961*42e9a92fSRobert Love 					 0, SLAB_HWCACHE_ALIGN, NULL);
1962*42e9a92fSRobert Love 	if (!fc_em_cachep)
1963*42e9a92fSRobert Love 		return -ENOMEM;
1964*42e9a92fSRobert Love 	return 0;
1965*42e9a92fSRobert Love }
1966*42e9a92fSRobert Love 
1967*42e9a92fSRobert Love void fc_destroy_exch_mgr(void)
1968*42e9a92fSRobert Love {
1969*42e9a92fSRobert Love 	kmem_cache_destroy(fc_em_cachep);
1970*42e9a92fSRobert Love }
1971