1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/timer.h>
27#include <linux/slab.h>
28#include <linux/err.h>
29#include <linux/export.h>
30#include <linux/log2.h>
31
32#include <scsi/fc/fc_fc2.h>
33
34#include <scsi/libfc.h>
35#include <scsi/fc_encode.h>
36
37#include "fc_libfc.h"
38
39u16 fc_cpu_mask;
40EXPORT_SYMBOL(fc_cpu_mask);
41static u16 fc_cpu_order;
42static struct kmem_cache *fc_em_cachep;
43static struct workqueue_struct *fc_exch_workqueue;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69struct fc_exch_pool {
70 spinlock_t lock;
71 struct list_head ex_list;
72 u16 next_index;
73 u16 total_exches;
74
75
76 u16 left;
77 u16 right;
78} ____cacheline_aligned_in_smp;
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94struct fc_exch_mgr {
95 struct fc_exch_pool __percpu *pool;
96 mempool_t *ep_pool;
97 enum fc_class class;
98 struct kref kref;
99 u16 min_xid;
100 u16 max_xid;
101 u16 pool_max_index;
102
103 struct {
104 atomic_t no_free_exch;
105 atomic_t no_free_exch_xid;
106 atomic_t xid_not_found;
107 atomic_t xid_busy;
108 atomic_t seq_not_found;
109 atomic_t non_bls_resp;
110 } stats;
111};
112
113
114
115
116
117
118
119
120
121
122
123
124
125struct fc_exch_mgr_anchor {
126 struct list_head ema_list;
127 struct fc_exch_mgr *mp;
128 bool (*match)(struct fc_frame *);
129};
130
131static void fc_exch_rrq(struct fc_exch *);
132static void fc_seq_ls_acc(struct fc_frame *);
133static void fc_seq_ls_rjt(struct fc_frame *, enum fc_els_rjt_reason,
134 enum fc_els_rjt_explan);
135static void fc_exch_els_rec(struct fc_frame *);
136static void fc_exch_els_rrq(struct fc_frame *);
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220static char *fc_exch_rctl_names[] = FC_RCTL_NAMES_INIT;
221
222
223
224
225
226
227
228
229
230
231static inline const char *fc_exch_name_lookup(unsigned int op, char **table,
232 unsigned int max_index)
233{
234 const char *name = NULL;
235
236 if (op < max_index)
237 name = table[op];
238 if (!name)
239 name = "unknown";
240 return name;
241}
242
243
244
245
246
247static const char *fc_exch_rctl_name(unsigned int op)
248{
249 return fc_exch_name_lookup(op, fc_exch_rctl_names,
250 ARRAY_SIZE(fc_exch_rctl_names));
251}
252
253
254
255
256
257static inline void fc_exch_hold(struct fc_exch *ep)
258{
259 atomic_inc(&ep->ex_refcnt);
260}
261
262
263
264
265
266
267
268
269
270
271
272static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp,
273 u32 f_ctl)
274{
275 struct fc_frame_header *fh = fc_frame_header_get(fp);
276 u16 fill;
277
278 fr_sof(fp) = ep->class;
279 if (ep->seq.cnt)
280 fr_sof(fp) = fc_sof_normal(ep->class);
281
282 if (f_ctl & FC_FC_END_SEQ) {
283 fr_eof(fp) = FC_EOF_T;
284 if (fc_sof_needs_ack(ep->class))
285 fr_eof(fp) = FC_EOF_N;
286
287
288
289
290
291
292
293
294
295 fill = fr_len(fp) & 3;
296 if (fill) {
297 fill = 4 - fill;
298
299 skb_put(fp_skb(fp), fill);
300 hton24(fh->fh_f_ctl, f_ctl | fill);
301 }
302 } else {
303 WARN_ON(fr_len(fp) % 4 != 0);
304 fr_eof(fp) = FC_EOF_N;
305 }
306
307
308 fh->fh_ox_id = htons(ep->oxid);
309 fh->fh_rx_id = htons(ep->rxid);
310 fh->fh_seq_id = ep->seq.id;
311 fh->fh_seq_cnt = htons(ep->seq.cnt);
312}
313
314
315
316
317
318
319
320
321static void fc_exch_release(struct fc_exch *ep)
322{
323 struct fc_exch_mgr *mp;
324
325 if (atomic_dec_and_test(&ep->ex_refcnt)) {
326 mp = ep->em;
327 if (ep->destructor)
328 ep->destructor(&ep->seq, ep->arg);
329 WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE));
330 mempool_free(ep, mp->ep_pool);
331 }
332}
333
334
335
336
337
338static inline void fc_exch_timer_cancel(struct fc_exch *ep)
339{
340 if (cancel_delayed_work(&ep->timeout_work)) {
341 FC_EXCH_DBG(ep, "Exchange timer canceled\n");
342 atomic_dec(&ep->ex_refcnt);
343 }
344}
345
346
347
348
349
350
351
352
353
354
355static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
356 unsigned int timer_msec)
357{
358 if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
359 return;
360
361 FC_EXCH_DBG(ep, "Exchange timer armed : %d msecs\n", timer_msec);
362
363 fc_exch_hold(ep);
364 if (!queue_delayed_work(fc_exch_workqueue, &ep->timeout_work,
365 msecs_to_jiffies(timer_msec)))
366 fc_exch_release(ep);
367}
368
369
370
371
372
373
374static void fc_exch_timer_set(struct fc_exch *ep, unsigned int timer_msec)
375{
376 spin_lock_bh(&ep->ex_lock);
377 fc_exch_timer_set_locked(ep, timer_msec);
378 spin_unlock_bh(&ep->ex_lock);
379}
380
381
382
383
384
385
386
387static int fc_exch_done_locked(struct fc_exch *ep)
388{
389 int rc = 1;
390
391
392
393
394
395
396
397 if (ep->state & FC_EX_DONE)
398 return rc;
399 ep->esb_stat |= ESB_ST_COMPLETE;
400
401 if (!(ep->esb_stat & ESB_ST_REC_QUAL)) {
402 ep->state |= FC_EX_DONE;
403 fc_exch_timer_cancel(ep);
404 rc = 0;
405 }
406 return rc;
407}
408
409
410
411
412
413
414
415
416
417
418static inline struct fc_exch *fc_exch_ptr_get(struct fc_exch_pool *pool,
419 u16 index)
420{
421 struct fc_exch **exches = (struct fc_exch **)(pool + 1);
422 return exches[index];
423}
424
425
426
427
428
429
430
431static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
432 struct fc_exch *ep)
433{
434 ((struct fc_exch **)(pool + 1))[index] = ep;
435}
436
437
438
439
440
441static void fc_exch_delete(struct fc_exch *ep)
442{
443 struct fc_exch_pool *pool;
444 u16 index;
445
446 pool = ep->pool;
447 spin_lock_bh(&pool->lock);
448 WARN_ON(pool->total_exches <= 0);
449 pool->total_exches--;
450
451
452 index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
453 if (pool->left == FC_XID_UNKNOWN)
454 pool->left = index;
455 else if (pool->right == FC_XID_UNKNOWN)
456 pool->right = index;
457 else
458 pool->next_index = index;
459
460 fc_exch_ptr_set(pool, index, NULL);
461 list_del(&ep->ex_list);
462 spin_unlock_bh(&pool->lock);
463 fc_exch_release(ep);
464}
465
466static int fc_seq_send_locked(struct fc_lport *lport, struct fc_seq *sp,
467 struct fc_frame *fp)
468{
469 struct fc_exch *ep;
470 struct fc_frame_header *fh = fc_frame_header_get(fp);
471 int error = -ENXIO;
472 u32 f_ctl;
473 u8 fh_type = fh->fh_type;
474
475 ep = fc_seq_exch(sp);
476
477 if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL)) {
478 fc_frame_free(fp);
479 goto out;
480 }
481
482 WARN_ON(!(ep->esb_stat & ESB_ST_SEQ_INIT));
483
484 f_ctl = ntoh24(fh->fh_f_ctl);
485 fc_exch_setup_hdr(ep, fp, f_ctl);
486 fr_encaps(fp) = ep->encaps;
487
488
489
490
491
492
493 if (fr_max_payload(fp))
494 sp->cnt += DIV_ROUND_UP((fr_len(fp) - sizeof(*fh)),
495 fr_max_payload(fp));
496 else
497 sp->cnt++;
498
499
500
501
502 error = lport->tt.frame_send(lport, fp);
503
504 if (fh_type == FC_TYPE_BLS)
505 goto out;
506
507
508
509
510
511
512 ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ;
513 if (f_ctl & FC_FC_SEQ_INIT)
514 ep->esb_stat &= ~ESB_ST_SEQ_INIT;
515out:
516 return error;
517}
518
519
520
521
522
523
524
525
526
527
528static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
529 struct fc_frame *fp)
530{
531 struct fc_exch *ep;
532 int error;
533 ep = fc_seq_exch(sp);
534 spin_lock_bh(&ep->ex_lock);
535 error = fc_seq_send_locked(lport, sp, fp);
536 spin_unlock_bh(&ep->ex_lock);
537 return error;
538}
539
540
541
542
543
544
545
546
547
548
549static struct fc_seq *fc_seq_alloc(struct fc_exch *ep, u8 seq_id)
550{
551 struct fc_seq *sp;
552
553 sp = &ep->seq;
554 sp->ssb_stat = 0;
555 sp->cnt = 0;
556 sp->id = seq_id;
557 return sp;
558}
559
560
561
562
563
564
565static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp)
566{
567 struct fc_exch *ep = fc_seq_exch(sp);
568
569 sp = fc_seq_alloc(ep, ep->seq_id++);
570 FC_EXCH_DBG(ep, "f_ctl %6x seq %2x\n",
571 ep->f_ctl, sp->id);
572 return sp;
573}
574
575
576
577
578
579
580static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
581{
582 struct fc_exch *ep = fc_seq_exch(sp);
583
584 spin_lock_bh(&ep->ex_lock);
585 sp = fc_seq_start_next_locked(sp);
586 spin_unlock_bh(&ep->ex_lock);
587
588 return sp;
589}
590
591
592
593
594
595
596static void fc_seq_set_resp(struct fc_seq *sp,
597 void (*resp)(struct fc_seq *, struct fc_frame *,
598 void *),
599 void *arg)
600{
601 struct fc_exch *ep = fc_seq_exch(sp);
602 DEFINE_WAIT(wait);
603
604 spin_lock_bh(&ep->ex_lock);
605 while (ep->resp_active && ep->resp_task != current) {
606 prepare_to_wait(&ep->resp_wq, &wait, TASK_UNINTERRUPTIBLE);
607 spin_unlock_bh(&ep->ex_lock);
608
609 schedule();
610
611 spin_lock_bh(&ep->ex_lock);
612 }
613 finish_wait(&ep->resp_wq, &wait);
614 ep->resp = resp;
615 ep->arg = arg;
616 spin_unlock_bh(&ep->ex_lock);
617}
618
619
620
621
622
623
624
625
626
627
628static int fc_exch_abort_locked(struct fc_exch *ep,
629 unsigned int timer_msec)
630{
631 struct fc_seq *sp;
632 struct fc_frame *fp;
633 int error;
634
635 if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) ||
636 ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP))
637 return -ENXIO;
638
639
640
641
642 sp = fc_seq_start_next_locked(&ep->seq);
643 if (!sp)
644 return -ENOMEM;
645
646 if (timer_msec)
647 fc_exch_timer_set_locked(ep, timer_msec);
648
649 if (ep->sid) {
650
651
652
653 fp = fc_frame_alloc(ep->lp, 0);
654 if (fp) {
655 ep->esb_stat |= ESB_ST_SEQ_INIT;
656 fc_fill_fc_hdr(fp, FC_RCTL_BA_ABTS, ep->did, ep->sid,
657 FC_TYPE_BLS, FC_FC_END_SEQ |
658 FC_FC_SEQ_INIT, 0);
659 error = fc_seq_send_locked(ep->lp, sp, fp);
660 } else {
661 error = -ENOBUFS;
662 }
663 } else {
664
665
666
667
668 error = 0;
669 }
670 ep->esb_stat |= ESB_ST_ABNORMAL;
671 return error;
672}
673
674
675
676
677
678
679
680
681
682
683static int fc_seq_exch_abort(const struct fc_seq *req_sp,
684 unsigned int timer_msec)
685{
686 struct fc_exch *ep;
687 int error;
688
689 ep = fc_seq_exch(req_sp);
690 spin_lock_bh(&ep->ex_lock);
691 error = fc_exch_abort_locked(ep, timer_msec);
692 spin_unlock_bh(&ep->ex_lock);
693 return error;
694}
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp,
719 struct fc_frame *fp)
720{
721 void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
722 void *arg;
723 bool res = false;
724
725 spin_lock_bh(&ep->ex_lock);
726 ep->resp_active++;
727 if (ep->resp_task != current)
728 ep->resp_task = !ep->resp_task ? current : NULL;
729 resp = ep->resp;
730 arg = ep->arg;
731 spin_unlock_bh(&ep->ex_lock);
732
733 if (resp) {
734 resp(sp, fp, arg);
735 res = true;
736 } else if (!IS_ERR(fp)) {
737 fc_frame_free(fp);
738 }
739
740 spin_lock_bh(&ep->ex_lock);
741 if (--ep->resp_active == 0)
742 ep->resp_task = NULL;
743 spin_unlock_bh(&ep->ex_lock);
744
745 if (ep->resp_active == 0)
746 wake_up(&ep->resp_wq);
747
748 return res;
749}
750
751
752
753
754
755static void fc_exch_timeout(struct work_struct *work)
756{
757 struct fc_exch *ep = container_of(work, struct fc_exch,
758 timeout_work.work);
759 struct fc_seq *sp = &ep->seq;
760 u32 e_stat;
761 int rc = 1;
762
763 FC_EXCH_DBG(ep, "Exchange timed out\n");
764
765 spin_lock_bh(&ep->ex_lock);
766 if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
767 goto unlock;
768
769 e_stat = ep->esb_stat;
770 if (e_stat & ESB_ST_COMPLETE) {
771 ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL;
772 spin_unlock_bh(&ep->ex_lock);
773 if (e_stat & ESB_ST_REC_QUAL)
774 fc_exch_rrq(ep);
775 goto done;
776 } else {
777 if (e_stat & ESB_ST_ABNORMAL)
778 rc = fc_exch_done_locked(ep);
779 spin_unlock_bh(&ep->ex_lock);
780 if (!rc)
781 fc_exch_delete(ep);
782 fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_TIMEOUT));
783 fc_seq_set_resp(sp, NULL, ep->arg);
784 fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
785 goto done;
786 }
787unlock:
788 spin_unlock_bh(&ep->ex_lock);
789done:
790
791
792
793 fc_exch_release(ep);
794}
795
796
797
798
799
800
801
802
803static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
804 struct fc_exch_mgr *mp)
805{
806 struct fc_exch *ep;
807 unsigned int cpu;
808 u16 index;
809 struct fc_exch_pool *pool;
810
811
812 ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
813 if (!ep) {
814 atomic_inc(&mp->stats.no_free_exch);
815 goto out;
816 }
817 memset(ep, 0, sizeof(*ep));
818
819 cpu = get_cpu();
820 pool = per_cpu_ptr(mp->pool, cpu);
821 spin_lock_bh(&pool->lock);
822 put_cpu();
823
824
825 if (pool->left != FC_XID_UNKNOWN) {
826 index = pool->left;
827 pool->left = FC_XID_UNKNOWN;
828 goto hit;
829 }
830 if (pool->right != FC_XID_UNKNOWN) {
831 index = pool->right;
832 pool->right = FC_XID_UNKNOWN;
833 goto hit;
834 }
835
836 index = pool->next_index;
837
838 while (fc_exch_ptr_get(pool, index)) {
839 index = index == mp->pool_max_index ? 0 : index + 1;
840 if (index == pool->next_index)
841 goto err;
842 }
843 pool->next_index = index == mp->pool_max_index ? 0 : index + 1;
844hit:
845 fc_exch_hold(ep);
846 spin_lock_init(&ep->ex_lock);
847
848
849
850
851
852 spin_lock_bh(&ep->ex_lock);
853
854 fc_exch_ptr_set(pool, index, ep);
855 list_add_tail(&ep->ex_list, &pool->ex_list);
856 fc_seq_alloc(ep, ep->seq_id++);
857 pool->total_exches++;
858 spin_unlock_bh(&pool->lock);
859
860
861
862
863 ep->oxid = ep->xid = (index << fc_cpu_order | cpu) + mp->min_xid;
864 ep->em = mp;
865 ep->pool = pool;
866 ep->lp = lport;
867 ep->f_ctl = FC_FC_FIRST_SEQ;
868 ep->rxid = FC_XID_UNKNOWN;
869 ep->class = mp->class;
870 ep->resp_active = 0;
871 init_waitqueue_head(&ep->resp_wq);
872 INIT_DELAYED_WORK(&ep->timeout_work, fc_exch_timeout);
873out:
874 return ep;
875err:
876 spin_unlock_bh(&pool->lock);
877 atomic_inc(&mp->stats.no_free_exch_xid);
878 mempool_free(ep, mp->ep_pool);
879 return NULL;
880}
881
882
883
884
885
886
887
888
889
890
891
892
893static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
894 struct fc_frame *fp)
895{
896 struct fc_exch_mgr_anchor *ema;
897
898 list_for_each_entry(ema, &lport->ema_list, ema_list)
899 if (!ema->match || ema->match(fp))
900 return fc_exch_em_alloc(lport, ema->mp);
901 return NULL;
902}
903
904
905
906
907
908
909static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
910{
911 struct fc_exch_pool *pool;
912 struct fc_exch *ep = NULL;
913
914 if ((xid >= mp->min_xid) && (xid <= mp->max_xid)) {
915 pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask);
916 spin_lock_bh(&pool->lock);
917 ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
918 if (ep) {
919 WARN_ON(ep->xid != xid);
920 fc_exch_hold(ep);
921 }
922 spin_unlock_bh(&pool->lock);
923 }
924 return ep;
925}
926
927
928
929
930
931
932
933
934
935static void fc_exch_done(struct fc_seq *sp)
936{
937 struct fc_exch *ep = fc_seq_exch(sp);
938 int rc;
939
940 spin_lock_bh(&ep->ex_lock);
941 rc = fc_exch_done_locked(ep);
942 spin_unlock_bh(&ep->ex_lock);
943
944 fc_seq_set_resp(sp, NULL, ep->arg);
945 if (!rc)
946 fc_exch_delete(ep);
947}
948
949
950
951
952
953
954
955
956
957static struct fc_exch *fc_exch_resp(struct fc_lport *lport,
958 struct fc_exch_mgr *mp,
959 struct fc_frame *fp)
960{
961 struct fc_exch *ep;
962 struct fc_frame_header *fh;
963
964 ep = fc_exch_alloc(lport, fp);
965 if (ep) {
966 ep->class = fc_frame_class(fp);
967
968
969
970
971 ep->f_ctl |= FC_FC_EX_CTX;
972 ep->f_ctl &= ~FC_FC_FIRST_SEQ;
973 fh = fc_frame_header_get(fp);
974 ep->sid = ntoh24(fh->fh_d_id);
975 ep->did = ntoh24(fh->fh_s_id);
976 ep->oid = ep->did;
977
978
979
980
981
982
983 ep->rxid = ep->xid;
984 ep->oxid = ntohs(fh->fh_ox_id);
985 ep->esb_stat |= ESB_ST_RESP | ESB_ST_SEQ_INIT;
986 if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0)
987 ep->esb_stat &= ~ESB_ST_SEQ_INIT;
988
989 fc_exch_hold(ep);
990 spin_unlock_bh(&ep->ex_lock);
991 }
992 return ep;
993}
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
1006 struct fc_exch_mgr *mp,
1007 struct fc_frame *fp)
1008{
1009 struct fc_frame_header *fh = fc_frame_header_get(fp);
1010 struct fc_exch *ep = NULL;
1011 struct fc_seq *sp = NULL;
1012 enum fc_pf_rjt_reason reject = FC_RJT_NONE;
1013 u32 f_ctl;
1014 u16 xid;
1015
1016 f_ctl = ntoh24(fh->fh_f_ctl);
1017 WARN_ON((f_ctl & FC_FC_SEQ_CTX) != 0);
1018
1019
1020
1021
1022 if (f_ctl & FC_FC_EX_CTX) {
1023 xid = ntohs(fh->fh_ox_id);
1024 ep = fc_exch_find(mp, xid);
1025 if (!ep) {
1026 atomic_inc(&mp->stats.xid_not_found);
1027 reject = FC_RJT_OX_ID;
1028 goto out;
1029 }
1030 if (ep->rxid == FC_XID_UNKNOWN)
1031 ep->rxid = ntohs(fh->fh_rx_id);
1032 else if (ep->rxid != ntohs(fh->fh_rx_id)) {
1033 reject = FC_RJT_OX_ID;
1034 goto rel;
1035 }
1036 } else {
1037 xid = ntohs(fh->fh_rx_id);
1038
1039
1040
1041
1042
1043
1044 if (xid == 0 && fh->fh_r_ctl == FC_RCTL_ELS_REQ &&
1045 fc_frame_payload_op(fp) == ELS_TEST) {
1046 fh->fh_rx_id = htons(FC_XID_UNKNOWN);
1047 xid = FC_XID_UNKNOWN;
1048 }
1049
1050
1051
1052
1053 ep = fc_exch_find(mp, xid);
1054 if ((f_ctl & FC_FC_FIRST_SEQ) && fc_sof_is_init(fr_sof(fp))) {
1055 if (ep) {
1056 atomic_inc(&mp->stats.xid_busy);
1057 reject = FC_RJT_RX_ID;
1058 goto rel;
1059 }
1060 ep = fc_exch_resp(lport, mp, fp);
1061 if (!ep) {
1062 reject = FC_RJT_EXCH_EST;
1063 goto out;
1064 }
1065 xid = ep->xid;
1066 } else if (!ep) {
1067 atomic_inc(&mp->stats.xid_not_found);
1068 reject = FC_RJT_RX_ID;
1069 goto out;
1070 }
1071 }
1072
1073 spin_lock_bh(&ep->ex_lock);
1074
1075
1076
1077
1078 if (fc_sof_is_init(fr_sof(fp))) {
1079 sp = &ep->seq;
1080 sp->ssb_stat |= SSB_ST_RESP;
1081 sp->id = fh->fh_seq_id;
1082 } else {
1083 sp = &ep->seq;
1084 if (sp->id != fh->fh_seq_id) {
1085 atomic_inc(&mp->stats.seq_not_found);
1086 if (f_ctl & FC_FC_END_SEQ) {
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101 sp->ssb_stat |= SSB_ST_RESP;
1102 sp->id = fh->fh_seq_id;
1103 } else {
1104 spin_unlock_bh(&ep->ex_lock);
1105
1106
1107 reject = FC_RJT_SEQ_ID;
1108 goto rel;
1109 }
1110 }
1111 }
1112 WARN_ON(ep != fc_seq_exch(sp));
1113
1114 if (f_ctl & FC_FC_SEQ_INIT)
1115 ep->esb_stat |= ESB_ST_SEQ_INIT;
1116 spin_unlock_bh(&ep->ex_lock);
1117
1118 fr_seq(fp) = sp;
1119out:
1120 return reject;
1121rel:
1122 fc_exch_done(&ep->seq);
1123 fc_exch_release(ep);
1124 return reject;
1125}
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135static struct fc_seq *fc_seq_lookup_orig(struct fc_exch_mgr *mp,
1136 struct fc_frame *fp)
1137{
1138 struct fc_frame_header *fh = fc_frame_header_get(fp);
1139 struct fc_exch *ep;
1140 struct fc_seq *sp = NULL;
1141 u32 f_ctl;
1142 u16 xid;
1143
1144 f_ctl = ntoh24(fh->fh_f_ctl);
1145 WARN_ON((f_ctl & FC_FC_SEQ_CTX) != FC_FC_SEQ_CTX);
1146 xid = ntohs((f_ctl & FC_FC_EX_CTX) ? fh->fh_ox_id : fh->fh_rx_id);
1147 ep = fc_exch_find(mp, xid);
1148 if (!ep)
1149 return NULL;
1150 if (ep->seq.id == fh->fh_seq_id) {
1151
1152
1153
1154 sp = &ep->seq;
1155 if ((f_ctl & FC_FC_EX_CTX) != 0 &&
1156 ep->rxid == FC_XID_UNKNOWN) {
1157 ep->rxid = ntohs(fh->fh_rx_id);
1158 }
1159 }
1160 fc_exch_release(ep);
1161 return sp;
1162}
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172static void fc_exch_set_addr(struct fc_exch *ep,
1173 u32 orig_id, u32 resp_id)
1174{
1175 ep->oid = orig_id;
1176 if (ep->esb_stat & ESB_ST_RESP) {
1177 ep->sid = resp_id;
1178 ep->did = orig_id;
1179 } else {
1180 ep->sid = orig_id;
1181 ep->did = resp_id;
1182 }
1183}
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd,
1195 struct fc_seq_els_data *els_data)
1196{
1197 switch (els_cmd) {
1198 case ELS_LS_RJT:
1199 fc_seq_ls_rjt(fp, els_data->reason, els_data->explan);
1200 break;
1201 case ELS_LS_ACC:
1202 fc_seq_ls_acc(fp);
1203 break;
1204 case ELS_RRQ:
1205 fc_exch_els_rrq(fp);
1206 break;
1207 case ELS_REC:
1208 fc_exch_els_rec(fp);
1209 break;
1210 default:
1211 FC_LPORT_DBG(fr_dev(fp), "Invalid ELS CMD:%x\n", els_cmd);
1212 }
1213}
1214
1215
1216
1217
1218
1219
1220
1221
1222static void fc_seq_send_last(struct fc_seq *sp, struct fc_frame *fp,
1223 enum fc_rctl rctl, enum fc_fh_type fh_type)
1224{
1225 u32 f_ctl;
1226 struct fc_exch *ep = fc_seq_exch(sp);
1227
1228 f_ctl = FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT;
1229 f_ctl |= ep->f_ctl;
1230 fc_fill_fc_hdr(fp, rctl, ep->did, ep->sid, fh_type, f_ctl, 0);
1231 fc_seq_send_locked(ep->lp, sp, fp);
1232}
1233
1234
1235
1236
1237
1238
1239
1240
1241static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
1242{
1243 struct fc_frame *fp;
1244 struct fc_frame_header *rx_fh;
1245 struct fc_frame_header *fh;
1246 struct fc_exch *ep = fc_seq_exch(sp);
1247 struct fc_lport *lport = ep->lp;
1248 unsigned int f_ctl;
1249
1250
1251
1252
1253 if (fc_sof_needs_ack(fr_sof(rx_fp))) {
1254 fp = fc_frame_alloc(lport, 0);
1255 if (!fp)
1256 return;
1257
1258 fh = fc_frame_header_get(fp);
1259 fh->fh_r_ctl = FC_RCTL_ACK_1;
1260 fh->fh_type = FC_TYPE_BLS;
1261
1262
1263
1264
1265
1266
1267
1268
1269 rx_fh = fc_frame_header_get(rx_fp);
1270 f_ctl = ntoh24(rx_fh->fh_f_ctl);
1271 f_ctl &= FC_FC_EX_CTX | FC_FC_SEQ_CTX |
1272 FC_FC_FIRST_SEQ | FC_FC_LAST_SEQ |
1273 FC_FC_END_SEQ | FC_FC_END_CONN | FC_FC_SEQ_INIT |
1274 FC_FC_RETX_SEQ | FC_FC_UNI_TX;
1275 f_ctl ^= FC_FC_EX_CTX | FC_FC_SEQ_CTX;
1276 hton24(fh->fh_f_ctl, f_ctl);
1277
1278 fc_exch_setup_hdr(ep, fp, f_ctl);
1279 fh->fh_seq_id = rx_fh->fh_seq_id;
1280 fh->fh_seq_cnt = rx_fh->fh_seq_cnt;
1281 fh->fh_parm_offset = htonl(1);
1282
1283 fr_sof(fp) = fr_sof(rx_fp);
1284 if (f_ctl & FC_FC_END_SEQ)
1285 fr_eof(fp) = FC_EOF_T;
1286 else
1287 fr_eof(fp) = FC_EOF_N;
1288
1289 lport->tt.frame_send(lport, fp);
1290 }
1291}
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
1302 enum fc_ba_rjt_reason reason,
1303 enum fc_ba_rjt_explan explan)
1304{
1305 struct fc_frame *fp;
1306 struct fc_frame_header *rx_fh;
1307 struct fc_frame_header *fh;
1308 struct fc_ba_rjt *rp;
1309 struct fc_lport *lport;
1310 unsigned int f_ctl;
1311
1312 lport = fr_dev(rx_fp);
1313 fp = fc_frame_alloc(lport, sizeof(*rp));
1314 if (!fp)
1315 return;
1316 fh = fc_frame_header_get(fp);
1317 rx_fh = fc_frame_header_get(rx_fp);
1318
1319 memset(fh, 0, sizeof(*fh) + sizeof(*rp));
1320
1321 rp = fc_frame_payload_get(fp, sizeof(*rp));
1322 rp->br_reason = reason;
1323 rp->br_explan = explan;
1324
1325
1326
1327
1328 memcpy(fh->fh_s_id, rx_fh->fh_d_id, 3);
1329 memcpy(fh->fh_d_id, rx_fh->fh_s_id, 3);
1330 fh->fh_ox_id = rx_fh->fh_ox_id;
1331 fh->fh_rx_id = rx_fh->fh_rx_id;
1332 fh->fh_seq_cnt = rx_fh->fh_seq_cnt;
1333 fh->fh_r_ctl = FC_RCTL_BA_RJT;
1334 fh->fh_type = FC_TYPE_BLS;
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 f_ctl = ntoh24(rx_fh->fh_f_ctl);
1345 f_ctl &= FC_FC_EX_CTX | FC_FC_SEQ_CTX |
1346 FC_FC_END_CONN | FC_FC_SEQ_INIT |
1347 FC_FC_RETX_SEQ | FC_FC_UNI_TX;
1348 f_ctl ^= FC_FC_EX_CTX | FC_FC_SEQ_CTX;
1349 f_ctl |= FC_FC_LAST_SEQ | FC_FC_END_SEQ;
1350 f_ctl &= ~FC_FC_FIRST_SEQ;
1351 hton24(fh->fh_f_ctl, f_ctl);
1352
1353 fr_sof(fp) = fc_sof_class(fr_sof(rx_fp));
1354 fr_eof(fp) = FC_EOF_T;
1355 if (fc_sof_needs_ack(fr_sof(fp)))
1356 fr_eof(fp) = FC_EOF_N;
1357
1358 lport->tt.frame_send(lport, fp);
1359}
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
1371{
1372 struct fc_frame *fp;
1373 struct fc_ba_acc *ap;
1374 struct fc_frame_header *fh;
1375 struct fc_seq *sp;
1376
1377 if (!ep)
1378 goto reject;
1379
1380 fp = fc_frame_alloc(ep->lp, sizeof(*ap));
1381 if (!fp)
1382 goto free;
1383
1384 spin_lock_bh(&ep->ex_lock);
1385 if (ep->esb_stat & ESB_ST_COMPLETE) {
1386 spin_unlock_bh(&ep->ex_lock);
1387
1388 fc_frame_free(fp);
1389 goto reject;
1390 }
1391 if (!(ep->esb_stat & ESB_ST_REC_QUAL)) {
1392 ep->esb_stat |= ESB_ST_REC_QUAL;
1393 fc_exch_hold(ep);
1394 }
1395 fc_exch_timer_set_locked(ep, ep->r_a_tov);
1396 fh = fc_frame_header_get(fp);
1397 ap = fc_frame_payload_get(fp, sizeof(*ap));
1398 memset(ap, 0, sizeof(*ap));
1399 sp = &ep->seq;
1400 ap->ba_high_seq_cnt = htons(0xffff);
1401 if (sp->ssb_stat & SSB_ST_RESP) {
1402 ap->ba_seq_id = sp->id;
1403 ap->ba_seq_id_val = FC_BA_SEQ_ID_VAL;
1404 ap->ba_high_seq_cnt = fh->fh_seq_cnt;
1405 ap->ba_low_seq_cnt = htons(sp->cnt);
1406 }
1407 sp = fc_seq_start_next_locked(sp);
1408 fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS);
1409 ep->esb_stat |= ESB_ST_ABNORMAL;
1410 spin_unlock_bh(&ep->ex_lock);
1411
1412free:
1413 fc_frame_free(rx_fp);
1414 return;
1415
1416reject:
1417 fc_exch_send_ba_rjt(rx_fp, FC_BA_RJT_UNABLE, FC_BA_RJT_INV_XID);
1418 goto free;
1419}
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
1431{
1432 struct fc_exch_mgr_anchor *ema;
1433
1434 WARN_ON(lport != fr_dev(fp));
1435 WARN_ON(fr_seq(fp));
1436 fr_seq(fp) = NULL;
1437
1438 list_for_each_entry(ema, &lport->ema_list, ema_list)
1439 if ((!ema->match || ema->match(fp)) &&
1440 fc_seq_lookup_recip(lport, ema->mp, fp) == FC_RJT_NONE)
1441 break;
1442 return fr_seq(fp);
1443}
1444
1445
1446
1447
1448
1449static void fc_seq_release(struct fc_seq *sp)
1450{
1451 fc_exch_release(fc_seq_exch(sp));
1452}
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
1464 struct fc_frame *fp)
1465{
1466 struct fc_frame_header *fh = fc_frame_header_get(fp);
1467 struct fc_seq *sp = NULL;
1468 struct fc_exch *ep = NULL;
1469 enum fc_pf_rjt_reason reject;
1470
1471
1472
1473
1474 lport = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
1475 if (!lport) {
1476 fc_frame_free(fp);
1477 return;
1478 }
1479 fr_dev(fp) = lport;
1480
1481 BUG_ON(fr_seq(fp));
1482
1483
1484
1485
1486
1487 if (fh->fh_rx_id == htons(FC_XID_UNKNOWN))
1488 return lport->tt.lport_recv(lport, fp);
1489
1490 reject = fc_seq_lookup_recip(lport, mp, fp);
1491 if (reject == FC_RJT_NONE) {
1492 sp = fr_seq(fp);
1493 ep = fc_seq_exch(sp);
1494 fc_seq_send_ack(sp, fp);
1495 ep->encaps = fr_encaps(fp);
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508 if (!fc_invoke_resp(ep, sp, fp))
1509 lport->tt.lport_recv(lport, fp);
1510 fc_exch_release(ep);
1511 } else {
1512 FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n",
1513 reject);
1514 fc_frame_free(fp);
1515 }
1516}
1517
1518
1519
1520
1521
1522
1523
1524
1525static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1526{
1527 struct fc_frame_header *fh = fc_frame_header_get(fp);
1528 struct fc_seq *sp;
1529 struct fc_exch *ep;
1530 enum fc_sof sof;
1531 u32 f_ctl;
1532 int rc;
1533
1534 ep = fc_exch_find(mp, ntohs(fh->fh_ox_id));
1535 if (!ep) {
1536 atomic_inc(&mp->stats.xid_not_found);
1537 goto out;
1538 }
1539 if (ep->esb_stat & ESB_ST_COMPLETE) {
1540 atomic_inc(&mp->stats.xid_not_found);
1541 goto rel;
1542 }
1543 if (ep->rxid == FC_XID_UNKNOWN)
1544 ep->rxid = ntohs(fh->fh_rx_id);
1545 if (ep->sid != 0 && ep->sid != ntoh24(fh->fh_d_id)) {
1546 atomic_inc(&mp->stats.xid_not_found);
1547 goto rel;
1548 }
1549 if (ep->did != ntoh24(fh->fh_s_id) &&
1550 ep->did != FC_FID_FLOGI) {
1551 atomic_inc(&mp->stats.xid_not_found);
1552 goto rel;
1553 }
1554 sof = fr_sof(fp);
1555 sp = &ep->seq;
1556 if (fc_sof_is_init(sof)) {
1557 sp->ssb_stat |= SSB_ST_RESP;
1558 sp->id = fh->fh_seq_id;
1559 } else if (sp->id != fh->fh_seq_id) {
1560 atomic_inc(&mp->stats.seq_not_found);
1561 goto rel;
1562 }
1563
1564 f_ctl = ntoh24(fh->fh_f_ctl);
1565 fr_seq(fp) = sp;
1566
1567 spin_lock_bh(&ep->ex_lock);
1568 if (f_ctl & FC_FC_SEQ_INIT)
1569 ep->esb_stat |= ESB_ST_SEQ_INIT;
1570 spin_unlock_bh(&ep->ex_lock);
1571
1572 if (fc_sof_needs_ack(sof))
1573 fc_seq_send_ack(sp, fp);
1574
1575 if (fh->fh_type != FC_TYPE_FCP && fr_eof(fp) == FC_EOF_T &&
1576 (f_ctl & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==
1577 (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) {
1578 spin_lock_bh(&ep->ex_lock);
1579 rc = fc_exch_done_locked(ep);
1580 WARN_ON(fc_seq_exch(sp) != ep);
1581 spin_unlock_bh(&ep->ex_lock);
1582 if (!rc)
1583 fc_exch_delete(ep);
1584 }
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599 fc_invoke_resp(ep, sp, fp);
1600
1601 fc_exch_release(ep);
1602 return;
1603rel:
1604 fc_exch_release(ep);
1605out:
1606 fc_frame_free(fp);
1607}
1608
1609
1610
1611
1612
1613
1614
1615static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
1616{
1617 struct fc_seq *sp;
1618
1619 sp = fc_seq_lookup_orig(mp, fp);
1620
1621 if (!sp)
1622 atomic_inc(&mp->stats.xid_not_found);
1623 else
1624 atomic_inc(&mp->stats.non_bls_resp);
1625
1626 fc_frame_free(fp);
1627}
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
1638{
1639 struct fc_frame_header *fh;
1640 struct fc_ba_acc *ap;
1641 struct fc_seq *sp;
1642 u16 low;
1643 u16 high;
1644 int rc = 1, has_rec = 0;
1645
1646 fh = fc_frame_header_get(fp);
1647 FC_EXCH_DBG(ep, "exch: BLS rctl %x - %s\n", fh->fh_r_ctl,
1648 fc_exch_rctl_name(fh->fh_r_ctl));
1649
1650 if (cancel_delayed_work_sync(&ep->timeout_work)) {
1651 FC_EXCH_DBG(ep, "Exchange timer canceled due to ABTS response\n");
1652 fc_exch_release(ep);
1653 }
1654
1655 spin_lock_bh(&ep->ex_lock);
1656 switch (fh->fh_r_ctl) {
1657 case FC_RCTL_BA_ACC:
1658 ap = fc_frame_payload_get(fp, sizeof(*ap));
1659 if (!ap)
1660 break;
1661
1662
1663
1664
1665
1666
1667 low = ntohs(ap->ba_low_seq_cnt);
1668 high = ntohs(ap->ba_high_seq_cnt);
1669 if ((ep->esb_stat & ESB_ST_REC_QUAL) == 0 &&
1670 (ap->ba_seq_id_val != FC_BA_SEQ_ID_VAL ||
1671 ap->ba_seq_id == ep->seq_id) && low != high) {
1672 ep->esb_stat |= ESB_ST_REC_QUAL;
1673 fc_exch_hold(ep);
1674 has_rec = 1;
1675 }
1676 break;
1677 case FC_RCTL_BA_RJT:
1678 break;
1679 default:
1680 break;
1681 }
1682
1683
1684
1685
1686 sp = &ep->seq;
1687
1688
1689
1690 if (ep->fh_type != FC_TYPE_FCP &&
1691 ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ)
1692 rc = fc_exch_done_locked(ep);
1693 spin_unlock_bh(&ep->ex_lock);
1694
1695 fc_exch_hold(ep);
1696 if (!rc)
1697 fc_exch_delete(ep);
1698 fc_invoke_resp(ep, sp, fp);
1699 if (has_rec)
1700 fc_exch_timer_set(ep, ep->r_a_tov);
1701 fc_exch_release(ep);
1702}
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
1713{
1714 struct fc_frame_header *fh;
1715 struct fc_exch *ep;
1716 u32 f_ctl;
1717
1718 fh = fc_frame_header_get(fp);
1719 f_ctl = ntoh24(fh->fh_f_ctl);
1720 fr_seq(fp) = NULL;
1721
1722 ep = fc_exch_find(mp, (f_ctl & FC_FC_EX_CTX) ?
1723 ntohs(fh->fh_ox_id) : ntohs(fh->fh_rx_id));
1724 if (ep && (f_ctl & FC_FC_SEQ_INIT)) {
1725 spin_lock_bh(&ep->ex_lock);
1726 ep->esb_stat |= ESB_ST_SEQ_INIT;
1727 spin_unlock_bh(&ep->ex_lock);
1728 }
1729 if (f_ctl & FC_FC_SEQ_CTX) {
1730
1731
1732
1733
1734 switch (fh->fh_r_ctl) {
1735 case FC_RCTL_ACK_1:
1736 case FC_RCTL_ACK_0:
1737 break;
1738 default:
1739 if (ep)
1740 FC_EXCH_DBG(ep, "BLS rctl %x - %s received\n",
1741 fh->fh_r_ctl,
1742 fc_exch_rctl_name(fh->fh_r_ctl));
1743 break;
1744 }
1745 fc_frame_free(fp);
1746 } else {
1747 switch (fh->fh_r_ctl) {
1748 case FC_RCTL_BA_RJT:
1749 case FC_RCTL_BA_ACC:
1750 if (ep)
1751 fc_exch_abts_resp(ep, fp);
1752 else
1753 fc_frame_free(fp);
1754 break;
1755 case FC_RCTL_BA_ABTS:
1756 fc_exch_recv_abts(ep, fp);
1757 break;
1758 default:
1759 fc_frame_free(fp);
1760 break;
1761 }
1762 }
1763 if (ep)
1764 fc_exch_release(ep);
1765}
1766
1767
1768
1769
1770
1771
1772
1773
1774static void fc_seq_ls_acc(struct fc_frame *rx_fp)
1775{
1776 struct fc_lport *lport;
1777 struct fc_els_ls_acc *acc;
1778 struct fc_frame *fp;
1779
1780 lport = fr_dev(rx_fp);
1781 fp = fc_frame_alloc(lport, sizeof(*acc));
1782 if (!fp)
1783 return;
1784 acc = fc_frame_payload_get(fp, sizeof(*acc));
1785 memset(acc, 0, sizeof(*acc));
1786 acc->la_cmd = ELS_LS_ACC;
1787 fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
1788 lport->tt.frame_send(lport, fp);
1789}
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason,
1801 enum fc_els_rjt_explan explan)
1802{
1803 struct fc_lport *lport;
1804 struct fc_els_ls_rjt *rjt;
1805 struct fc_frame *fp;
1806
1807 lport = fr_dev(rx_fp);
1808 fp = fc_frame_alloc(lport, sizeof(*rjt));
1809 if (!fp)
1810 return;
1811 rjt = fc_frame_payload_get(fp, sizeof(*rjt));
1812 memset(rjt, 0, sizeof(*rjt));
1813 rjt->er_cmd = ELS_LS_RJT;
1814 rjt->er_reason = reason;
1815 rjt->er_explan = explan;
1816 fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
1817 lport->tt.frame_send(lport, fp);
1818}
1819
1820
1821
1822
1823
1824
1825
1826static void fc_exch_reset(struct fc_exch *ep)
1827{
1828 struct fc_seq *sp;
1829 int rc = 1;
1830
1831 spin_lock_bh(&ep->ex_lock);
1832 fc_exch_abort_locked(ep, 0);
1833 ep->state |= FC_EX_RST_CLEANUP;
1834 fc_exch_timer_cancel(ep);
1835 if (ep->esb_stat & ESB_ST_REC_QUAL)
1836 atomic_dec(&ep->ex_refcnt);
1837 ep->esb_stat &= ~ESB_ST_REC_QUAL;
1838 sp = &ep->seq;
1839 rc = fc_exch_done_locked(ep);
1840 spin_unlock_bh(&ep->ex_lock);
1841
1842 fc_exch_hold(ep);
1843
1844 if (!rc)
1845 fc_exch_delete(ep);
1846
1847 fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED));
1848 fc_seq_set_resp(sp, NULL, ep->arg);
1849 fc_exch_release(ep);
1850}
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864static void fc_exch_pool_reset(struct fc_lport *lport,
1865 struct fc_exch_pool *pool,
1866 u32 sid, u32 did)
1867{
1868 struct fc_exch *ep;
1869 struct fc_exch *next;
1870
1871 spin_lock_bh(&pool->lock);
1872restart:
1873 list_for_each_entry_safe(ep, next, &pool->ex_list, ex_list) {
1874 if ((lport == ep->lp) &&
1875 (sid == 0 || sid == ep->sid) &&
1876 (did == 0 || did == ep->did)) {
1877 fc_exch_hold(ep);
1878 spin_unlock_bh(&pool->lock);
1879
1880 fc_exch_reset(ep);
1881
1882 fc_exch_release(ep);
1883 spin_lock_bh(&pool->lock);
1884
1885
1886
1887
1888
1889 goto restart;
1890 }
1891 }
1892 pool->next_index = 0;
1893 pool->left = FC_XID_UNKNOWN;
1894 pool->right = FC_XID_UNKNOWN;
1895 spin_unlock_bh(&pool->lock);
1896}
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did)
1910{
1911 struct fc_exch_mgr_anchor *ema;
1912 unsigned int cpu;
1913
1914 list_for_each_entry(ema, &lport->ema_list, ema_list) {
1915 for_each_possible_cpu(cpu)
1916 fc_exch_pool_reset(lport,
1917 per_cpu_ptr(ema->mp->pool, cpu),
1918 sid, did);
1919 }
1920}
1921EXPORT_SYMBOL(fc_exch_mgr_reset);
1922
1923
1924
1925
1926
1927
1928
1929
1930static struct fc_exch *fc_exch_lookup(struct fc_lport *lport, u32 xid)
1931{
1932 struct fc_exch_mgr_anchor *ema;
1933
1934 list_for_each_entry(ema, &lport->ema_list, ema_list)
1935 if (ema->mp->min_xid <= xid && xid <= ema->mp->max_xid)
1936 return fc_exch_find(ema->mp, xid);
1937 return NULL;
1938}
1939
1940
1941
1942
1943
1944
1945
1946static void fc_exch_els_rec(struct fc_frame *rfp)
1947{
1948 struct fc_lport *lport;
1949 struct fc_frame *fp;
1950 struct fc_exch *ep;
1951 struct fc_els_rec *rp;
1952 struct fc_els_rec_acc *acc;
1953 enum fc_els_rjt_reason reason = ELS_RJT_LOGIC;
1954 enum fc_els_rjt_explan explan;
1955 u32 sid;
1956 u16 rxid;
1957 u16 oxid;
1958
1959 lport = fr_dev(rfp);
1960 rp = fc_frame_payload_get(rfp, sizeof(*rp));
1961 explan = ELS_EXPL_INV_LEN;
1962 if (!rp)
1963 goto reject;
1964 sid = ntoh24(rp->rec_s_id);
1965 rxid = ntohs(rp->rec_rx_id);
1966 oxid = ntohs(rp->rec_ox_id);
1967
1968 ep = fc_exch_lookup(lport,
1969 sid == fc_host_port_id(lport->host) ? oxid : rxid);
1970 explan = ELS_EXPL_OXID_RXID;
1971 if (!ep)
1972 goto reject;
1973 if (ep->oid != sid || oxid != ep->oxid)
1974 goto rel;
1975 if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid)
1976 goto rel;
1977 fp = fc_frame_alloc(lport, sizeof(*acc));
1978 if (!fp)
1979 goto out;
1980
1981 acc = fc_frame_payload_get(fp, sizeof(*acc));
1982 memset(acc, 0, sizeof(*acc));
1983 acc->reca_cmd = ELS_LS_ACC;
1984 acc->reca_ox_id = rp->rec_ox_id;
1985 memcpy(acc->reca_ofid, rp->rec_s_id, 3);
1986 acc->reca_rx_id = htons(ep->rxid);
1987 if (ep->sid == ep->oid)
1988 hton24(acc->reca_rfid, ep->did);
1989 else
1990 hton24(acc->reca_rfid, ep->sid);
1991 acc->reca_fc4value = htonl(ep->seq.rec_data);
1992 acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP |
1993 ESB_ST_SEQ_INIT |
1994 ESB_ST_COMPLETE));
1995 fc_fill_reply_hdr(fp, rfp, FC_RCTL_ELS_REP, 0);
1996 lport->tt.frame_send(lport, fp);
1997out:
1998 fc_exch_release(ep);
1999 return;
2000
2001rel:
2002 fc_exch_release(ep);
2003reject:
2004 fc_seq_ls_rjt(rfp, reason, explan);
2005}
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
2016{
2017 struct fc_exch *aborted_ep = arg;
2018 unsigned int op;
2019
2020 if (IS_ERR(fp)) {
2021 int err = PTR_ERR(fp);
2022
2023 if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT)
2024 goto cleanup;
2025 FC_EXCH_DBG(aborted_ep, "Cannot process RRQ, "
2026 "frame error %d\n", err);
2027 return;
2028 }
2029
2030 op = fc_frame_payload_op(fp);
2031 fc_frame_free(fp);
2032
2033 switch (op) {
2034 case ELS_LS_RJT:
2035 FC_EXCH_DBG(aborted_ep, "LS_RJT for RRQ\n");
2036
2037 case ELS_LS_ACC:
2038 goto cleanup;
2039 default:
2040 FC_EXCH_DBG(aborted_ep, "unexpected response op %x for RRQ\n",
2041 op);
2042 return;
2043 }
2044
2045cleanup:
2046 fc_exch_done(&aborted_ep->seq);
2047
2048 fc_exch_release(aborted_ep);
2049}
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
2072 struct fc_frame *fp,
2073 void (*resp)(struct fc_seq *,
2074 struct fc_frame *fp,
2075 void *arg),
2076 void (*destructor)(struct fc_seq *,
2077 void *),
2078 void *arg, u32 timer_msec)
2079{
2080 struct fc_exch *ep;
2081 struct fc_seq *sp = NULL;
2082 struct fc_frame_header *fh;
2083 struct fc_fcp_pkt *fsp = NULL;
2084 int rc = 1;
2085
2086 ep = fc_exch_alloc(lport, fp);
2087 if (!ep) {
2088 fc_frame_free(fp);
2089 return NULL;
2090 }
2091 ep->esb_stat |= ESB_ST_SEQ_INIT;
2092 fh = fc_frame_header_get(fp);
2093 fc_exch_set_addr(ep, ntoh24(fh->fh_s_id), ntoh24(fh->fh_d_id));
2094 ep->resp = resp;
2095 ep->destructor = destructor;
2096 ep->arg = arg;
2097 ep->r_a_tov = FC_DEF_R_A_TOV;
2098 ep->lp = lport;
2099 sp = &ep->seq;
2100
2101 ep->fh_type = fh->fh_type;
2102 ep->f_ctl = ntoh24(fh->fh_f_ctl);
2103 fc_exch_setup_hdr(ep, fp, ep->f_ctl);
2104 sp->cnt++;
2105
2106 if (ep->xid <= lport->lro_xid && fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD) {
2107 fsp = fr_fsp(fp);
2108 fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
2109 }
2110
2111 if (unlikely(lport->tt.frame_send(lport, fp)))
2112 goto err;
2113
2114 if (timer_msec)
2115 fc_exch_timer_set_locked(ep, timer_msec);
2116 ep->f_ctl &= ~FC_FC_FIRST_SEQ;
2117
2118 if (ep->f_ctl & FC_FC_SEQ_INIT)
2119 ep->esb_stat &= ~ESB_ST_SEQ_INIT;
2120 spin_unlock_bh(&ep->ex_lock);
2121 return sp;
2122err:
2123 if (fsp)
2124 fc_fcp_ddp_done(fsp);
2125 rc = fc_exch_done_locked(ep);
2126 spin_unlock_bh(&ep->ex_lock);
2127 if (!rc)
2128 fc_exch_delete(ep);
2129 return NULL;
2130}
2131
2132
2133
2134
2135
2136
2137
2138
2139static void fc_exch_rrq(struct fc_exch *ep)
2140{
2141 struct fc_lport *lport;
2142 struct fc_els_rrq *rrq;
2143 struct fc_frame *fp;
2144 u32 did;
2145
2146 lport = ep->lp;
2147
2148 fp = fc_frame_alloc(lport, sizeof(*rrq));
2149 if (!fp)
2150 goto retry;
2151
2152 rrq = fc_frame_payload_get(fp, sizeof(*rrq));
2153 memset(rrq, 0, sizeof(*rrq));
2154 rrq->rrq_cmd = ELS_RRQ;
2155 hton24(rrq->rrq_s_id, ep->sid);
2156 rrq->rrq_ox_id = htons(ep->oxid);
2157 rrq->rrq_rx_id = htons(ep->rxid);
2158
2159 did = ep->did;
2160 if (ep->esb_stat & ESB_ST_RESP)
2161 did = ep->sid;
2162
2163 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did,
2164 lport->port_id, FC_TYPE_ELS,
2165 FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
2166
2167 if (fc_exch_seq_send(lport, fp, fc_exch_rrq_resp, NULL, ep,
2168 lport->e_d_tov))
2169 return;
2170
2171retry:
2172 spin_lock_bh(&ep->ex_lock);
2173 if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) {
2174 spin_unlock_bh(&ep->ex_lock);
2175
2176 fc_exch_release(ep);
2177 return;
2178 }
2179 ep->esb_stat |= ESB_ST_REC_QUAL;
2180 fc_exch_timer_set_locked(ep, ep->r_a_tov);
2181 spin_unlock_bh(&ep->ex_lock);
2182}
2183
2184
2185
2186
2187
2188static void fc_exch_els_rrq(struct fc_frame *fp)
2189{
2190 struct fc_lport *lport;
2191 struct fc_exch *ep = NULL;
2192 struct fc_els_rrq *rp;
2193 u32 sid;
2194 u16 xid;
2195 enum fc_els_rjt_explan explan;
2196
2197 lport = fr_dev(fp);
2198 rp = fc_frame_payload_get(fp, sizeof(*rp));
2199 explan = ELS_EXPL_INV_LEN;
2200 if (!rp)
2201 goto reject;
2202
2203
2204
2205
2206 sid = ntoh24(rp->rrq_s_id);
2207 xid = fc_host_port_id(lport->host) == sid ?
2208 ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id);
2209 ep = fc_exch_lookup(lport, xid);
2210 explan = ELS_EXPL_OXID_RXID;
2211 if (!ep)
2212 goto reject;
2213 spin_lock_bh(&ep->ex_lock);
2214 if (ep->oxid != ntohs(rp->rrq_ox_id))
2215 goto unlock_reject;
2216 if (ep->rxid != ntohs(rp->rrq_rx_id) &&
2217 ep->rxid != FC_XID_UNKNOWN)
2218 goto unlock_reject;
2219 explan = ELS_EXPL_SID;
2220 if (ep->sid != sid)
2221 goto unlock_reject;
2222
2223
2224
2225
2226 if (ep->esb_stat & ESB_ST_REC_QUAL) {
2227 ep->esb_stat &= ~ESB_ST_REC_QUAL;
2228 atomic_dec(&ep->ex_refcnt);
2229 }
2230 if (ep->esb_stat & ESB_ST_COMPLETE)
2231 fc_exch_timer_cancel(ep);
2232
2233 spin_unlock_bh(&ep->ex_lock);
2234
2235
2236
2237
2238 fc_seq_ls_acc(fp);
2239 goto out;
2240
2241unlock_reject:
2242 spin_unlock_bh(&ep->ex_lock);
2243reject:
2244 fc_seq_ls_rjt(fp, ELS_RJT_LOGIC, explan);
2245out:
2246 if (ep)
2247 fc_exch_release(ep);
2248}
2249
2250
2251
2252
2253
2254void fc_exch_update_stats(struct fc_lport *lport)
2255{
2256 struct fc_host_statistics *st;
2257 struct fc_exch_mgr_anchor *ema;
2258 struct fc_exch_mgr *mp;
2259
2260 st = &lport->host_stats;
2261
2262 list_for_each_entry(ema, &lport->ema_list, ema_list) {
2263 mp = ema->mp;
2264 st->fc_no_free_exch += atomic_read(&mp->stats.no_free_exch);
2265 st->fc_no_free_exch_xid +=
2266 atomic_read(&mp->stats.no_free_exch_xid);
2267 st->fc_xid_not_found += atomic_read(&mp->stats.xid_not_found);
2268 st->fc_xid_busy += atomic_read(&mp->stats.xid_busy);
2269 st->fc_seq_not_found += atomic_read(&mp->stats.seq_not_found);
2270 st->fc_non_bls_resp += atomic_read(&mp->stats.non_bls_resp);
2271 }
2272}
2273EXPORT_SYMBOL(fc_exch_update_stats);
2274
2275
2276
2277
2278
2279
2280
2281struct fc_exch_mgr_anchor *fc_exch_mgr_add(struct fc_lport *lport,
2282 struct fc_exch_mgr *mp,
2283 bool (*match)(struct fc_frame *))
2284{
2285 struct fc_exch_mgr_anchor *ema;
2286
2287 ema = kmalloc(sizeof(*ema), GFP_ATOMIC);
2288 if (!ema)
2289 return ema;
2290
2291 ema->mp = mp;
2292 ema->match = match;
2293
2294 list_add_tail(&ema->ema_list, &lport->ema_list);
2295 kref_get(&mp->kref);
2296 return ema;
2297}
2298EXPORT_SYMBOL(fc_exch_mgr_add);
2299
2300
2301
2302
2303
2304static void fc_exch_mgr_destroy(struct kref *kref)
2305{
2306 struct fc_exch_mgr *mp = container_of(kref, struct fc_exch_mgr, kref);
2307
2308 mempool_destroy(mp->ep_pool);
2309 free_percpu(mp->pool);
2310 kfree(mp);
2311}
2312
2313
2314
2315
2316
2317void fc_exch_mgr_del(struct fc_exch_mgr_anchor *ema)
2318{
2319
2320 list_del(&ema->ema_list);
2321 kref_put(&ema->mp->kref, fc_exch_mgr_destroy);
2322 kfree(ema);
2323}
2324EXPORT_SYMBOL(fc_exch_mgr_del);
2325
2326
2327
2328
2329
2330
2331int fc_exch_mgr_list_clone(struct fc_lport *src, struct fc_lport *dst)
2332{
2333 struct fc_exch_mgr_anchor *ema, *tmp;
2334
2335 list_for_each_entry(ema, &src->ema_list, ema_list) {
2336 if (!fc_exch_mgr_add(dst, ema->mp, ema->match))
2337 goto err;
2338 }
2339 return 0;
2340err:
2341 list_for_each_entry_safe(ema, tmp, &dst->ema_list, ema_list)
2342 fc_exch_mgr_del(ema);
2343 return -ENOMEM;
2344}
2345EXPORT_SYMBOL(fc_exch_mgr_list_clone);
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
2356 enum fc_class class,
2357 u16 min_xid, u16 max_xid,
2358 bool (*match)(struct fc_frame *))
2359{
2360 struct fc_exch_mgr *mp;
2361 u16 pool_exch_range;
2362 size_t pool_size;
2363 unsigned int cpu;
2364 struct fc_exch_pool *pool;
2365
2366 if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN ||
2367 (min_xid & fc_cpu_mask) != 0) {
2368 FC_LPORT_DBG(lport, "Invalid min_xid 0x:%x and max_xid 0x:%x\n",
2369 min_xid, max_xid);
2370 return NULL;
2371 }
2372
2373
2374
2375
2376 mp = kzalloc(sizeof(struct fc_exch_mgr), GFP_ATOMIC);
2377 if (!mp)
2378 return NULL;
2379
2380 mp->class = class;
2381
2382 mp->min_xid = min_xid;
2383
2384
2385 pool_exch_range = (PCPU_MIN_UNIT_SIZE - sizeof(*pool)) /
2386 sizeof(struct fc_exch *);
2387 if ((max_xid - min_xid + 1) / (fc_cpu_mask + 1) > pool_exch_range) {
2388 mp->max_xid = pool_exch_range * (fc_cpu_mask + 1) +
2389 min_xid - 1;
2390 } else {
2391 mp->max_xid = max_xid;
2392 pool_exch_range = (mp->max_xid - mp->min_xid + 1) /
2393 (fc_cpu_mask + 1);
2394 }
2395
2396 mp->ep_pool = mempool_create_slab_pool(2, fc_em_cachep);
2397 if (!mp->ep_pool)
2398 goto free_mp;
2399
2400
2401
2402
2403
2404
2405 mp->pool_max_index = pool_exch_range - 1;
2406
2407
2408
2409
2410 pool_size = sizeof(*pool) + pool_exch_range * sizeof(struct fc_exch *);
2411 mp->pool = __alloc_percpu(pool_size, __alignof__(struct fc_exch_pool));
2412 if (!mp->pool)
2413 goto free_mempool;
2414 for_each_possible_cpu(cpu) {
2415 pool = per_cpu_ptr(mp->pool, cpu);
2416 pool->next_index = 0;
2417 pool->left = FC_XID_UNKNOWN;
2418 pool->right = FC_XID_UNKNOWN;
2419 spin_lock_init(&pool->lock);
2420 INIT_LIST_HEAD(&pool->ex_list);
2421 }
2422
2423 kref_init(&mp->kref);
2424 if (!fc_exch_mgr_add(lport, mp, match)) {
2425 free_percpu(mp->pool);
2426 goto free_mempool;
2427 }
2428
2429
2430
2431
2432
2433
2434 kref_put(&mp->kref, fc_exch_mgr_destroy);
2435 return mp;
2436
2437free_mempool:
2438 mempool_destroy(mp->ep_pool);
2439free_mp:
2440 kfree(mp);
2441 return NULL;
2442}
2443EXPORT_SYMBOL(fc_exch_mgr_alloc);
2444
2445
2446
2447
2448
2449void fc_exch_mgr_free(struct fc_lport *lport)
2450{
2451 struct fc_exch_mgr_anchor *ema, *next;
2452
2453 flush_workqueue(fc_exch_workqueue);
2454 list_for_each_entry_safe(ema, next, &lport->ema_list, ema_list)
2455 fc_exch_mgr_del(ema);
2456}
2457EXPORT_SYMBOL(fc_exch_mgr_free);
2458
2459
2460
2461
2462
2463
2464
2465
2466static struct fc_exch_mgr_anchor *fc_find_ema(u32 f_ctl,
2467 struct fc_lport *lport,
2468 struct fc_frame_header *fh)
2469{
2470 struct fc_exch_mgr_anchor *ema;
2471 u16 xid;
2472
2473 if (f_ctl & FC_FC_EX_CTX)
2474 xid = ntohs(fh->fh_ox_id);
2475 else {
2476 xid = ntohs(fh->fh_rx_id);
2477 if (xid == FC_XID_UNKNOWN)
2478 return list_entry(lport->ema_list.prev,
2479 typeof(*ema), ema_list);
2480 }
2481
2482 list_for_each_entry(ema, &lport->ema_list, ema_list) {
2483 if ((xid >= ema->mp->min_xid) &&
2484 (xid <= ema->mp->max_xid))
2485 return ema;
2486 }
2487 return NULL;
2488}
2489
2490
2491
2492
2493
2494void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
2495{
2496 struct fc_frame_header *fh = fc_frame_header_get(fp);
2497 struct fc_exch_mgr_anchor *ema;
2498 u32 f_ctl;
2499
2500
2501 if (!lport || lport->state == LPORT_ST_DISABLED) {
2502 FC_LPORT_DBG(lport, "Receiving frames for an lport that "
2503 "has not been initialized correctly\n");
2504 fc_frame_free(fp);
2505 return;
2506 }
2507
2508 f_ctl = ntoh24(fh->fh_f_ctl);
2509 ema = fc_find_ema(f_ctl, lport, fh);
2510 if (!ema) {
2511 FC_LPORT_DBG(lport, "Unable to find Exchange Manager Anchor,"
2512 "fc_ctl <0x%x>, xid <0x%x>\n",
2513 f_ctl,
2514 (f_ctl & FC_FC_EX_CTX) ?
2515 ntohs(fh->fh_ox_id) :
2516 ntohs(fh->fh_rx_id));
2517 fc_frame_free(fp);
2518 return;
2519 }
2520
2521
2522
2523
2524 switch (fr_eof(fp)) {
2525 case FC_EOF_T:
2526 if (f_ctl & FC_FC_END_SEQ)
2527 skb_trim(fp_skb(fp), fr_len(fp) - FC_FC_FILL(f_ctl));
2528
2529 case FC_EOF_N:
2530 if (fh->fh_type == FC_TYPE_BLS)
2531 fc_exch_recv_bls(ema->mp, fp);
2532 else if ((f_ctl & (FC_FC_EX_CTX | FC_FC_SEQ_CTX)) ==
2533 FC_FC_EX_CTX)
2534 fc_exch_recv_seq_resp(ema->mp, fp);
2535 else if (f_ctl & FC_FC_SEQ_CTX)
2536 fc_exch_recv_resp(ema->mp, fp);
2537 else
2538 fc_exch_recv_req(lport, ema->mp, fp);
2539 break;
2540 default:
2541 FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)",
2542 fr_eof(fp));
2543 fc_frame_free(fp);
2544 }
2545}
2546EXPORT_SYMBOL(fc_exch_recv);
2547
2548
2549
2550
2551
2552int fc_exch_init(struct fc_lport *lport)
2553{
2554 if (!lport->tt.seq_start_next)
2555 lport->tt.seq_start_next = fc_seq_start_next;
2556
2557 if (!lport->tt.seq_set_resp)
2558 lport->tt.seq_set_resp = fc_seq_set_resp;
2559
2560 if (!lport->tt.exch_seq_send)
2561 lport->tt.exch_seq_send = fc_exch_seq_send;
2562
2563 if (!lport->tt.seq_send)
2564 lport->tt.seq_send = fc_seq_send;
2565
2566 if (!lport->tt.seq_els_rsp_send)
2567 lport->tt.seq_els_rsp_send = fc_seq_els_rsp_send;
2568
2569 if (!lport->tt.exch_done)
2570 lport->tt.exch_done = fc_exch_done;
2571
2572 if (!lport->tt.exch_mgr_reset)
2573 lport->tt.exch_mgr_reset = fc_exch_mgr_reset;
2574
2575 if (!lport->tt.seq_exch_abort)
2576 lport->tt.seq_exch_abort = fc_seq_exch_abort;
2577
2578 if (!lport->tt.seq_assign)
2579 lport->tt.seq_assign = fc_seq_assign;
2580
2581 if (!lport->tt.seq_release)
2582 lport->tt.seq_release = fc_seq_release;
2583
2584 return 0;
2585}
2586EXPORT_SYMBOL(fc_exch_init);
2587
2588
2589
2590
2591int fc_setup_exch_mgr(void)
2592{
2593 fc_em_cachep = kmem_cache_create("libfc_em", sizeof(struct fc_exch),
2594 0, SLAB_HWCACHE_ALIGN, NULL);
2595 if (!fc_em_cachep)
2596 return -ENOMEM;
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612 fc_cpu_order = ilog2(roundup_pow_of_two(nr_cpu_ids));
2613 fc_cpu_mask = (1 << fc_cpu_order) - 1;
2614
2615 fc_exch_workqueue = create_singlethread_workqueue("fc_exch_workqueue");
2616 if (!fc_exch_workqueue)
2617 goto err;
2618 return 0;
2619err:
2620 kmem_cache_destroy(fc_em_cachep);
2621 return -ENOMEM;
2622}
2623
2624
2625
2626
2627void fc_destroy_exch_mgr(void)
2628{
2629 destroy_workqueue(fc_exch_workqueue);
2630 kmem_cache_destroy(fc_em_cachep);
2631}
2632