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