hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/nvme/target/fc.c
....@@ -1,18 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Copyright (c) 2016 Avago Technologies. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of version 2 of the GNU General Public License as
6
- * published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope that it will be useful.
9
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
10
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
11
- * PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO
12
- * THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
13
- * See the GNU General Public License for more details, a copy of which
14
- * can be found in the file COPYING included with this package
15
- *
164 */
175 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
186 #include <linux/module.h>
....@@ -26,6 +14,7 @@
2614 #include "nvmet.h"
2715 #include <linux/nvme-fc-driver.h>
2816 #include <linux/nvme-fc.h>
17
+#include "../host/fc.h"
2918
3019
3120 /* *************************** Data Structures/Defines ****************** */
....@@ -33,23 +22,21 @@
3322
3423 #define NVMET_LS_CTX_COUNT 256
3524
36
-/* for this implementation, assume small single frame rqst/rsp */
37
-#define NVME_FC_MAX_LS_BUFFER_SIZE 2048
38
-
3925 struct nvmet_fc_tgtport;
4026 struct nvmet_fc_tgt_assoc;
4127
42
-struct nvmet_fc_ls_iod {
43
- struct nvmefc_tgt_ls_req *lsreq;
28
+struct nvmet_fc_ls_iod { /* for an LS RQST RCV */
29
+ struct nvmefc_ls_rsp *lsrsp;
4430 struct nvmefc_tgt_fcp_req *fcpreq; /* only if RS */
4531
46
- struct list_head ls_list; /* tgtport->ls_list */
32
+ struct list_head ls_rcv_list; /* tgtport->ls_rcv_list */
4733
4834 struct nvmet_fc_tgtport *tgtport;
4935 struct nvmet_fc_tgt_assoc *assoc;
36
+ void *hosthandle;
5037
51
- u8 *rqstbuf;
52
- u8 *rspbuf;
38
+ union nvmefc_ls_requests *rqstbuf;
39
+ union nvmefc_ls_responses *rspbuf;
5340 u16 rqstdatalen;
5441 dma_addr_t rspdma;
5542
....@@ -57,6 +44,18 @@
5744
5845 struct work_struct work;
5946 } __aligned(sizeof(unsigned long long));
47
+
48
+struct nvmet_fc_ls_req_op { /* for an LS RQST XMT */
49
+ struct nvmefc_ls_req ls_req;
50
+
51
+ struct nvmet_fc_tgtport *tgtport;
52
+ void *hosthandle;
53
+
54
+ int ls_error;
55
+ struct list_head lsreq_list; /* tgtport->ls_req_list */
56
+ bool req_queued;
57
+};
58
+
6059
6160 /* desired maximum for a single sequence - if sg list allows it */
6261 #define NVMET_FC_MAX_SEQ_LENGTH (256 * 1024)
....@@ -86,8 +85,6 @@
8685 spinlock_t flock;
8786
8887 struct nvmet_req req;
89
- struct work_struct work;
90
- struct work_struct done_work;
9188 struct work_struct defer_work;
9289
9390 struct nvmet_fc_tgtport *tgtport;
....@@ -97,7 +94,6 @@
9794 };
9895
9996 struct nvmet_fc_tgtport {
100
-
10197 struct nvmet_fc_target_port fc_target_port;
10298
10399 struct list_head tgt_list; /* nvmet_fc_target_list */
....@@ -106,13 +102,23 @@
106102
107103 struct nvmet_fc_ls_iod *iod;
108104 spinlock_t lock;
109
- struct list_head ls_list;
105
+ struct list_head ls_rcv_list;
106
+ struct list_head ls_req_list;
110107 struct list_head ls_busylist;
111108 struct list_head assoc_list;
109
+ struct list_head host_list;
112110 struct ida assoc_cnt;
113
- struct nvmet_port *port;
111
+ struct nvmet_fc_port_entry *pe;
114112 struct kref ref;
115113 u32 max_sg_cnt;
114
+};
115
+
116
+struct nvmet_fc_port_entry {
117
+ struct nvmet_fc_tgtport *tgtport;
118
+ struct nvmet_port *port;
119
+ u64 node_name;
120
+ u64 port_name;
121
+ struct list_head pe_list;
116122 };
117123
118124 struct nvmet_fc_defer_fcp_req {
....@@ -126,28 +132,37 @@
126132 u16 sqsize;
127133 u16 ersp_ratio;
128134 __le16 sqhd;
129
- int cpu;
130135 atomic_t connected;
131136 atomic_t sqtail;
132137 atomic_t zrspcnt;
133138 atomic_t rsn;
134139 spinlock_t qlock;
135
- struct nvmet_port *port;
136140 struct nvmet_cq nvme_cq;
137141 struct nvmet_sq nvme_sq;
138142 struct nvmet_fc_tgt_assoc *assoc;
139
- struct nvmet_fc_fcp_iod *fod; /* array of fcp_iods */
140143 struct list_head fod_list;
141144 struct list_head pending_cmd_list;
142145 struct list_head avail_defer_list;
143146 struct workqueue_struct *work_q;
144147 struct kref ref;
148
+ struct nvmet_fc_fcp_iod fod[]; /* array of fcp_iods */
145149 } __aligned(sizeof(unsigned long long));
150
+
151
+struct nvmet_fc_hostport {
152
+ struct nvmet_fc_tgtport *tgtport;
153
+ void *hosthandle;
154
+ struct list_head host_list;
155
+ struct kref ref;
156
+ u8 invalid;
157
+};
146158
147159 struct nvmet_fc_tgt_assoc {
148160 u64 association_id;
149161 u32 a_id;
162
+ atomic_t terminating;
150163 struct nvmet_fc_tgtport *tgtport;
164
+ struct nvmet_fc_hostport *hostport;
165
+ struct nvmet_fc_ls_iod *rcv_disconn;
151166 struct list_head a_list;
152167 struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES + 1];
153168 struct kref ref;
....@@ -221,11 +236,10 @@
221236
222237 static LIST_HEAD(nvmet_fc_target_list);
223238 static DEFINE_IDA(nvmet_fc_tgtport_cnt);
239
+static LIST_HEAD(nvmet_fc_portentry_list);
224240
225241
226242 static void nvmet_fc_handle_ls_rqst_work(struct work_struct *work);
227
-static void nvmet_fc_handle_fcp_rqst_work(struct work_struct *work);
228
-static void nvmet_fc_fcp_rqst_op_done_work(struct work_struct *work);
229243 static void nvmet_fc_fcp_rqst_op_defer_work(struct work_struct *work);
230244 static void nvmet_fc_tgt_a_put(struct nvmet_fc_tgt_assoc *assoc);
231245 static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc);
....@@ -236,6 +250,8 @@
236250 static void nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
237251 struct nvmet_fc_fcp_iod *fod);
238252 static void nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc);
253
+static void nvmet_fc_xmt_ls_rsp(struct nvmet_fc_tgtport *tgtport,
254
+ struct nvmet_fc_ls_iod *iod);
239255
240256
241257 /* *********************** FC-NVME DMA Handling **************************** */
....@@ -327,6 +343,188 @@
327343 }
328344
329345
346
+/* ********************** FC-NVME LS XMT Handling ************************* */
347
+
348
+
349
+static void
350
+__nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop)
351
+{
352
+ struct nvmet_fc_tgtport *tgtport = lsop->tgtport;
353
+ struct nvmefc_ls_req *lsreq = &lsop->ls_req;
354
+ unsigned long flags;
355
+
356
+ spin_lock_irqsave(&tgtport->lock, flags);
357
+
358
+ if (!lsop->req_queued) {
359
+ spin_unlock_irqrestore(&tgtport->lock, flags);
360
+ return;
361
+ }
362
+
363
+ list_del(&lsop->lsreq_list);
364
+
365
+ lsop->req_queued = false;
366
+
367
+ spin_unlock_irqrestore(&tgtport->lock, flags);
368
+
369
+ fc_dma_unmap_single(tgtport->dev, lsreq->rqstdma,
370
+ (lsreq->rqstlen + lsreq->rsplen),
371
+ DMA_BIDIRECTIONAL);
372
+
373
+ nvmet_fc_tgtport_put(tgtport);
374
+}
375
+
376
+static int
377
+__nvmet_fc_send_ls_req(struct nvmet_fc_tgtport *tgtport,
378
+ struct nvmet_fc_ls_req_op *lsop,
379
+ void (*done)(struct nvmefc_ls_req *req, int status))
380
+{
381
+ struct nvmefc_ls_req *lsreq = &lsop->ls_req;
382
+ unsigned long flags;
383
+ int ret = 0;
384
+
385
+ if (!tgtport->ops->ls_req)
386
+ return -EOPNOTSUPP;
387
+
388
+ if (!nvmet_fc_tgtport_get(tgtport))
389
+ return -ESHUTDOWN;
390
+
391
+ lsreq->done = done;
392
+ lsop->req_queued = false;
393
+ INIT_LIST_HEAD(&lsop->lsreq_list);
394
+
395
+ lsreq->rqstdma = fc_dma_map_single(tgtport->dev, lsreq->rqstaddr,
396
+ lsreq->rqstlen + lsreq->rsplen,
397
+ DMA_BIDIRECTIONAL);
398
+ if (fc_dma_mapping_error(tgtport->dev, lsreq->rqstdma)) {
399
+ ret = -EFAULT;
400
+ goto out_puttgtport;
401
+ }
402
+ lsreq->rspdma = lsreq->rqstdma + lsreq->rqstlen;
403
+
404
+ spin_lock_irqsave(&tgtport->lock, flags);
405
+
406
+ list_add_tail(&lsop->lsreq_list, &tgtport->ls_req_list);
407
+
408
+ lsop->req_queued = true;
409
+
410
+ spin_unlock_irqrestore(&tgtport->lock, flags);
411
+
412
+ ret = tgtport->ops->ls_req(&tgtport->fc_target_port, lsop->hosthandle,
413
+ lsreq);
414
+ if (ret)
415
+ goto out_unlink;
416
+
417
+ return 0;
418
+
419
+out_unlink:
420
+ lsop->ls_error = ret;
421
+ spin_lock_irqsave(&tgtport->lock, flags);
422
+ lsop->req_queued = false;
423
+ list_del(&lsop->lsreq_list);
424
+ spin_unlock_irqrestore(&tgtport->lock, flags);
425
+ fc_dma_unmap_single(tgtport->dev, lsreq->rqstdma,
426
+ (lsreq->rqstlen + lsreq->rsplen),
427
+ DMA_BIDIRECTIONAL);
428
+out_puttgtport:
429
+ nvmet_fc_tgtport_put(tgtport);
430
+
431
+ return ret;
432
+}
433
+
434
+static int
435
+nvmet_fc_send_ls_req_async(struct nvmet_fc_tgtport *tgtport,
436
+ struct nvmet_fc_ls_req_op *lsop,
437
+ void (*done)(struct nvmefc_ls_req *req, int status))
438
+{
439
+ /* don't wait for completion */
440
+
441
+ return __nvmet_fc_send_ls_req(tgtport, lsop, done);
442
+}
443
+
444
+static void
445
+nvmet_fc_disconnect_assoc_done(struct nvmefc_ls_req *lsreq, int status)
446
+{
447
+ struct nvmet_fc_ls_req_op *lsop =
448
+ container_of(lsreq, struct nvmet_fc_ls_req_op, ls_req);
449
+
450
+ __nvmet_fc_finish_ls_req(lsop);
451
+
452
+ /* fc-nvme target doesn't care about success or failure of cmd */
453
+
454
+ kfree(lsop);
455
+}
456
+
457
+/*
458
+ * This routine sends a FC-NVME LS to disconnect (aka terminate)
459
+ * the FC-NVME Association. Terminating the association also
460
+ * terminates the FC-NVME connections (per queue, both admin and io
461
+ * queues) that are part of the association. E.g. things are torn
462
+ * down, and the related FC-NVME Association ID and Connection IDs
463
+ * become invalid.
464
+ *
465
+ * The behavior of the fc-nvme target is such that it's
466
+ * understanding of the association and connections will implicitly
467
+ * be torn down. The action is implicit as it may be due to a loss of
468
+ * connectivity with the fc-nvme host, so the target may never get a
469
+ * response even if it tried. As such, the action of this routine
470
+ * is to asynchronously send the LS, ignore any results of the LS, and
471
+ * continue on with terminating the association. If the fc-nvme host
472
+ * is present and receives the LS, it too can tear down.
473
+ */
474
+static void
475
+nvmet_fc_xmt_disconnect_assoc(struct nvmet_fc_tgt_assoc *assoc)
476
+{
477
+ struct nvmet_fc_tgtport *tgtport = assoc->tgtport;
478
+ struct fcnvme_ls_disconnect_assoc_rqst *discon_rqst;
479
+ struct fcnvme_ls_disconnect_assoc_acc *discon_acc;
480
+ struct nvmet_fc_ls_req_op *lsop;
481
+ struct nvmefc_ls_req *lsreq;
482
+ int ret;
483
+
484
+ /*
485
+ * If ls_req is NULL or no hosthandle, it's an older lldd and no
486
+ * message is normal. Otherwise, send unless the hostport has
487
+ * already been invalidated by the lldd.
488
+ */
489
+ if (!tgtport->ops->ls_req || !assoc->hostport ||
490
+ assoc->hostport->invalid)
491
+ return;
492
+
493
+ lsop = kzalloc((sizeof(*lsop) +
494
+ sizeof(*discon_rqst) + sizeof(*discon_acc) +
495
+ tgtport->ops->lsrqst_priv_sz), GFP_KERNEL);
496
+ if (!lsop) {
497
+ dev_info(tgtport->dev,
498
+ "{%d:%d} send Disconnect Association failed: ENOMEM\n",
499
+ tgtport->fc_target_port.port_num, assoc->a_id);
500
+ return;
501
+ }
502
+
503
+ discon_rqst = (struct fcnvme_ls_disconnect_assoc_rqst *)&lsop[1];
504
+ discon_acc = (struct fcnvme_ls_disconnect_assoc_acc *)&discon_rqst[1];
505
+ lsreq = &lsop->ls_req;
506
+ if (tgtport->ops->lsrqst_priv_sz)
507
+ lsreq->private = (void *)&discon_acc[1];
508
+ else
509
+ lsreq->private = NULL;
510
+
511
+ lsop->tgtport = tgtport;
512
+ lsop->hosthandle = assoc->hostport->hosthandle;
513
+
514
+ nvmefc_fmt_lsreq_discon_assoc(lsreq, discon_rqst, discon_acc,
515
+ assoc->association_id);
516
+
517
+ ret = nvmet_fc_send_ls_req_async(tgtport, lsop,
518
+ nvmet_fc_disconnect_assoc_done);
519
+ if (ret) {
520
+ dev_info(tgtport->dev,
521
+ "{%d:%d} XMT Disconnect Association failed: %d\n",
522
+ tgtport->fc_target_port.port_num, assoc->a_id, ret);
523
+ kfree(lsop);
524
+ }
525
+}
526
+
527
+
330528 /* *********************** FC-NVME Port Management ************************ */
331529
332530
....@@ -346,17 +544,18 @@
346544 for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) {
347545 INIT_WORK(&iod->work, nvmet_fc_handle_ls_rqst_work);
348546 iod->tgtport = tgtport;
349
- list_add_tail(&iod->ls_list, &tgtport->ls_list);
547
+ list_add_tail(&iod->ls_rcv_list, &tgtport->ls_rcv_list);
350548
351
- iod->rqstbuf = kcalloc(2, NVME_FC_MAX_LS_BUFFER_SIZE,
352
- GFP_KERNEL);
549
+ iod->rqstbuf = kzalloc(sizeof(union nvmefc_ls_requests) +
550
+ sizeof(union nvmefc_ls_responses),
551
+ GFP_KERNEL);
353552 if (!iod->rqstbuf)
354553 goto out_fail;
355554
356
- iod->rspbuf = iod->rqstbuf + NVME_FC_MAX_LS_BUFFER_SIZE;
555
+ iod->rspbuf = (union nvmefc_ls_responses *)&iod->rqstbuf[1];
357556
358557 iod->rspdma = fc_dma_map_single(tgtport->dev, iod->rspbuf,
359
- NVME_FC_MAX_LS_BUFFER_SIZE,
558
+ sizeof(*iod->rspbuf),
360559 DMA_TO_DEVICE);
361560 if (fc_dma_mapping_error(tgtport->dev, iod->rspdma))
362561 goto out_fail;
....@@ -366,12 +565,12 @@
366565
367566 out_fail:
368567 kfree(iod->rqstbuf);
369
- list_del(&iod->ls_list);
568
+ list_del(&iod->ls_rcv_list);
370569 for (iod--, i--; i >= 0; iod--, i--) {
371570 fc_dma_unmap_single(tgtport->dev, iod->rspdma,
372
- NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
571
+ sizeof(*iod->rspbuf), DMA_TO_DEVICE);
373572 kfree(iod->rqstbuf);
374
- list_del(&iod->ls_list);
573
+ list_del(&iod->ls_rcv_list);
375574 }
376575
377576 kfree(iod);
....@@ -387,10 +586,10 @@
387586
388587 for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) {
389588 fc_dma_unmap_single(tgtport->dev,
390
- iod->rspdma, NVME_FC_MAX_LS_BUFFER_SIZE,
589
+ iod->rspdma, sizeof(*iod->rspbuf),
391590 DMA_TO_DEVICE);
392591 kfree(iod->rqstbuf);
393
- list_del(&iod->ls_list);
592
+ list_del(&iod->ls_rcv_list);
394593 }
395594 kfree(tgtport->iod);
396595 }
....@@ -402,10 +601,10 @@
402601 unsigned long flags;
403602
404603 spin_lock_irqsave(&tgtport->lock, flags);
405
- iod = list_first_entry_or_null(&tgtport->ls_list,
406
- struct nvmet_fc_ls_iod, ls_list);
604
+ iod = list_first_entry_or_null(&tgtport->ls_rcv_list,
605
+ struct nvmet_fc_ls_iod, ls_rcv_list);
407606 if (iod)
408
- list_move_tail(&iod->ls_list, &tgtport->ls_busylist);
607
+ list_move_tail(&iod->ls_rcv_list, &tgtport->ls_busylist);
409608 spin_unlock_irqrestore(&tgtport->lock, flags);
410609 return iod;
411610 }
....@@ -418,7 +617,7 @@
418617 unsigned long flags;
419618
420619 spin_lock_irqsave(&tgtport->lock, flags);
421
- list_move(&iod->ls_list, &tgtport->ls_list);
620
+ list_move(&iod->ls_rcv_list, &tgtport->ls_rcv_list);
422621 spin_unlock_irqrestore(&tgtport->lock, flags);
423622 }
424623
....@@ -430,8 +629,6 @@
430629 int i;
431630
432631 for (i = 0; i < queue->sqsize; fod++, i++) {
433
- INIT_WORK(&fod->work, nvmet_fc_handle_fcp_rqst_work);
434
- INIT_WORK(&fod->done_work, nvmet_fc_fcp_rqst_op_done_work);
435632 INIT_WORK(&fod->defer_work, nvmet_fc_fcp_rqst_op_defer_work);
436633 fod->tgtport = tgtport;
437634 fod->queue = queue;
....@@ -509,10 +706,7 @@
509706 fcpreq->hwqid = queue->qid ?
510707 ((queue->qid - 1) % tgtport->ops->max_hw_queues) : 0;
511708
512
- if (tgtport->ops->target_features & NVMET_FCTGTFEAT_CMD_IN_ISR)
513
- queue_work_on(queue->cpu, queue->work_q, &fod->work);
514
- else
515
- nvmet_fc_handle_fcp_rqst(tgtport, fod);
709
+ nvmet_fc_handle_fcp_rqst(tgtport, fod);
516710 }
517711
518712 static void
....@@ -591,30 +785,6 @@
591785 queue_work(queue->work_q, &fod->defer_work);
592786 }
593787
594
-static int
595
-nvmet_fc_queue_to_cpu(struct nvmet_fc_tgtport *tgtport, int qid)
596
-{
597
- int cpu, idx, cnt;
598
-
599
- if (tgtport->ops->max_hw_queues == 1)
600
- return WORK_CPU_UNBOUND;
601
-
602
- /* Simple cpu selection based on qid modulo active cpu count */
603
- idx = !qid ? 0 : (qid - 1) % num_active_cpus();
604
-
605
- /* find the n'th active cpu */
606
- for (cpu = 0, cnt = 0; ; ) {
607
- if (cpu_active(cpu)) {
608
- if (cnt == idx)
609
- break;
610
- cnt++;
611
- }
612
- cpu = (cpu + 1) % num_possible_cpus();
613
- }
614
-
615
- return cpu;
616
-}
617
-
618788 static struct nvmet_fc_tgt_queue *
619789 nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc,
620790 u16 qid, u16 sqsize)
....@@ -626,9 +796,7 @@
626796 if (qid > NVMET_NR_QUEUES)
627797 return NULL;
628798
629
- queue = kzalloc((sizeof(*queue) +
630
- (sizeof(struct nvmet_fc_fcp_iod) * sqsize)),
631
- GFP_KERNEL);
799
+ queue = kzalloc(struct_size(queue, fod, sqsize), GFP_KERNEL);
632800 if (!queue)
633801 return NULL;
634802
....@@ -641,12 +809,9 @@
641809 if (!queue->work_q)
642810 goto out_a_put;
643811
644
- queue->fod = (struct nvmet_fc_fcp_iod *)&queue[1];
645812 queue->qid = qid;
646813 queue->sqsize = sqsize;
647814 queue->assoc = assoc;
648
- queue->port = assoc->tgtport->port;
649
- queue->cpu = nvmet_fc_queue_to_cpu(assoc->tgtport, qid);
650815 INIT_LIST_HEAD(&queue->fod_list);
651816 INIT_LIST_HEAD(&queue->avail_defer_list);
652817 INIT_LIST_HEAD(&queue->pending_cmd_list);
....@@ -721,31 +886,33 @@
721886 struct nvmet_fc_fcp_iod *fod = queue->fod;
722887 struct nvmet_fc_defer_fcp_req *deferfcp, *tempptr;
723888 unsigned long flags;
724
- int i, writedataactive;
889
+ int i;
725890 bool disconnect;
726891
727892 disconnect = atomic_xchg(&queue->connected, 0);
728893
894
+ /* if not connected, nothing to do */
895
+ if (!disconnect)
896
+ return;
897
+
729898 spin_lock_irqsave(&queue->qlock, flags);
730
- /* about outstanding io's */
899
+ /* abort outstanding io's */
731900 for (i = 0; i < queue->sqsize; fod++, i++) {
732901 if (fod->active) {
733902 spin_lock(&fod->flock);
734903 fod->abort = true;
735
- writedataactive = fod->writedataactive;
736
- spin_unlock(&fod->flock);
737904 /*
738905 * only call lldd abort routine if waiting for
739906 * writedata. other outstanding ops should finish
740907 * on their own.
741908 */
742
- if (writedataactive) {
743
- spin_lock(&fod->flock);
909
+ if (fod->writedataactive) {
744910 fod->aborted = true;
745911 spin_unlock(&fod->flock);
746912 tgtport->ops->fcp_abort(
747913 &tgtport->fc_target_port, fod->fcpreq);
748
- }
914
+ } else
915
+ spin_unlock(&fod->flock);
749916 }
750917 }
751918
....@@ -785,8 +952,7 @@
785952
786953 flush_workqueue(queue->work_q);
787954
788
- if (disconnect)
789
- nvmet_sq_destroy(&queue->nvme_sq);
955
+ nvmet_sq_destroy(&queue->nvme_sq);
790956
791957 nvmet_fc_tgt_q_put(queue);
792958 }
....@@ -821,6 +987,102 @@
821987 }
822988
823989 static void
990
+nvmet_fc_hostport_free(struct kref *ref)
991
+{
992
+ struct nvmet_fc_hostport *hostport =
993
+ container_of(ref, struct nvmet_fc_hostport, ref);
994
+ struct nvmet_fc_tgtport *tgtport = hostport->tgtport;
995
+ unsigned long flags;
996
+
997
+ spin_lock_irqsave(&tgtport->lock, flags);
998
+ list_del(&hostport->host_list);
999
+ spin_unlock_irqrestore(&tgtport->lock, flags);
1000
+ if (tgtport->ops->host_release && hostport->invalid)
1001
+ tgtport->ops->host_release(hostport->hosthandle);
1002
+ kfree(hostport);
1003
+ nvmet_fc_tgtport_put(tgtport);
1004
+}
1005
+
1006
+static void
1007
+nvmet_fc_hostport_put(struct nvmet_fc_hostport *hostport)
1008
+{
1009
+ kref_put(&hostport->ref, nvmet_fc_hostport_free);
1010
+}
1011
+
1012
+static int
1013
+nvmet_fc_hostport_get(struct nvmet_fc_hostport *hostport)
1014
+{
1015
+ return kref_get_unless_zero(&hostport->ref);
1016
+}
1017
+
1018
+static void
1019
+nvmet_fc_free_hostport(struct nvmet_fc_hostport *hostport)
1020
+{
1021
+ /* if LLDD not implemented, leave as NULL */
1022
+ if (!hostport || !hostport->hosthandle)
1023
+ return;
1024
+
1025
+ nvmet_fc_hostport_put(hostport);
1026
+}
1027
+
1028
+static struct nvmet_fc_hostport *
1029
+nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
1030
+{
1031
+ struct nvmet_fc_hostport *newhost, *host, *match = NULL;
1032
+ unsigned long flags;
1033
+
1034
+ /* if LLDD not implemented, leave as NULL */
1035
+ if (!hosthandle)
1036
+ return NULL;
1037
+
1038
+ /* take reference for what will be the newly allocated hostport */
1039
+ if (!nvmet_fc_tgtport_get(tgtport))
1040
+ return ERR_PTR(-EINVAL);
1041
+
1042
+ newhost = kzalloc(sizeof(*newhost), GFP_KERNEL);
1043
+ if (!newhost) {
1044
+ spin_lock_irqsave(&tgtport->lock, flags);
1045
+ list_for_each_entry(host, &tgtport->host_list, host_list) {
1046
+ if (host->hosthandle == hosthandle && !host->invalid) {
1047
+ if (nvmet_fc_hostport_get(host)) {
1048
+ match = host;
1049
+ break;
1050
+ }
1051
+ }
1052
+ }
1053
+ spin_unlock_irqrestore(&tgtport->lock, flags);
1054
+ /* no allocation - release reference */
1055
+ nvmet_fc_tgtport_put(tgtport);
1056
+ return (match) ? match : ERR_PTR(-ENOMEM);
1057
+ }
1058
+
1059
+ newhost->tgtport = tgtport;
1060
+ newhost->hosthandle = hosthandle;
1061
+ INIT_LIST_HEAD(&newhost->host_list);
1062
+ kref_init(&newhost->ref);
1063
+
1064
+ spin_lock_irqsave(&tgtport->lock, flags);
1065
+ list_for_each_entry(host, &tgtport->host_list, host_list) {
1066
+ if (host->hosthandle == hosthandle && !host->invalid) {
1067
+ if (nvmet_fc_hostport_get(host)) {
1068
+ match = host;
1069
+ break;
1070
+ }
1071
+ }
1072
+ }
1073
+ if (match) {
1074
+ kfree(newhost);
1075
+ newhost = NULL;
1076
+ /* releasing allocation - release reference */
1077
+ nvmet_fc_tgtport_put(tgtport);
1078
+ } else
1079
+ list_add_tail(&newhost->host_list, &tgtport->host_list);
1080
+ spin_unlock_irqrestore(&tgtport->lock, flags);
1081
+
1082
+ return (match) ? match : newhost;
1083
+}
1084
+
1085
+static void
8241086 nvmet_fc_delete_assoc(struct work_struct *work)
8251087 {
8261088 struct nvmet_fc_tgt_assoc *assoc =
....@@ -831,7 +1093,7 @@
8311093 }
8321094
8331095 static struct nvmet_fc_tgt_assoc *
834
-nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport)
1096
+nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
8351097 {
8361098 struct nvmet_fc_tgt_assoc *assoc, *tmpassoc;
8371099 unsigned long flags;
....@@ -848,13 +1110,18 @@
8481110 goto out_free_assoc;
8491111
8501112 if (!nvmet_fc_tgtport_get(tgtport))
851
- goto out_ida_put;
1113
+ goto out_ida;
1114
+
1115
+ assoc->hostport = nvmet_fc_alloc_hostport(tgtport, hosthandle);
1116
+ if (IS_ERR(assoc->hostport))
1117
+ goto out_put;
8521118
8531119 assoc->tgtport = tgtport;
8541120 assoc->a_id = idx;
8551121 INIT_LIST_HEAD(&assoc->a_list);
8561122 kref_init(&assoc->ref);
8571123 INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc);
1124
+ atomic_set(&assoc->terminating, 0);
8581125
8591126 while (needrandom) {
8601127 get_random_bytes(&ran, sizeof(ran) - BYTES_FOR_QID);
....@@ -862,11 +1129,12 @@
8621129
8631130 spin_lock_irqsave(&tgtport->lock, flags);
8641131 needrandom = false;
865
- list_for_each_entry(tmpassoc, &tgtport->assoc_list, a_list)
1132
+ list_for_each_entry(tmpassoc, &tgtport->assoc_list, a_list) {
8661133 if (ran == tmpassoc->association_id) {
8671134 needrandom = true;
8681135 break;
8691136 }
1137
+ }
8701138 if (!needrandom) {
8711139 assoc->association_id = ran;
8721140 list_add_tail(&assoc->a_list, &tgtport->assoc_list);
....@@ -876,7 +1144,9 @@
8761144
8771145 return assoc;
8781146
879
-out_ida_put:
1147
+out_put:
1148
+ nvmet_fc_tgtport_put(tgtport);
1149
+out_ida:
8801150 ida_simple_remove(&tgtport->assoc_cnt, idx);
8811151 out_free_assoc:
8821152 kfree(assoc);
....@@ -889,12 +1159,24 @@
8891159 struct nvmet_fc_tgt_assoc *assoc =
8901160 container_of(ref, struct nvmet_fc_tgt_assoc, ref);
8911161 struct nvmet_fc_tgtport *tgtport = assoc->tgtport;
1162
+ struct nvmet_fc_ls_iod *oldls;
8921163 unsigned long flags;
8931164
1165
+ /* Send Disconnect now that all i/o has completed */
1166
+ nvmet_fc_xmt_disconnect_assoc(assoc);
1167
+
1168
+ nvmet_fc_free_hostport(assoc->hostport);
8941169 spin_lock_irqsave(&tgtport->lock, flags);
8951170 list_del(&assoc->a_list);
1171
+ oldls = assoc->rcv_disconn;
8961172 spin_unlock_irqrestore(&tgtport->lock, flags);
1173
+ /* if pending Rcv Disconnect Association LS, send rsp now */
1174
+ if (oldls)
1175
+ nvmet_fc_xmt_ls_rsp(tgtport, oldls);
8971176 ida_simple_remove(&tgtport->assoc_cnt, assoc->a_id);
1177
+ dev_info(tgtport->dev,
1178
+ "{%d:%d} Association freed\n",
1179
+ tgtport->fc_target_port.port_num, assoc->a_id);
8981180 kfree(assoc);
8991181 nvmet_fc_tgtport_put(tgtport);
9001182 }
....@@ -917,7 +1199,13 @@
9171199 struct nvmet_fc_tgtport *tgtport = assoc->tgtport;
9181200 struct nvmet_fc_tgt_queue *queue;
9191201 unsigned long flags;
920
- int i;
1202
+ int i, terminating;
1203
+
1204
+ terminating = atomic_xchg(&assoc->terminating, 1);
1205
+
1206
+ /* if already terminating, do nothing */
1207
+ if (terminating)
1208
+ return;
9211209
9221210 spin_lock_irqsave(&tgtport->lock, flags);
9231211 for (i = NVMET_NR_QUEUES; i >= 0; i--) {
....@@ -932,6 +1220,10 @@
9321220 }
9331221 }
9341222 spin_unlock_irqrestore(&tgtport->lock, flags);
1223
+
1224
+ dev_info(tgtport->dev,
1225
+ "{%d:%d} Association deleted\n",
1226
+ tgtport->fc_target_port.port_num, assoc->a_id);
9351227
9361228 nvmet_fc_tgt_a_put(assoc);
9371229 }
....@@ -948,7 +1240,8 @@
9481240 list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
9491241 if (association_id == assoc->association_id) {
9501242 ret = assoc;
951
- nvmet_fc_tgt_a_get(assoc);
1243
+ if (!nvmet_fc_tgt_a_get(assoc))
1244
+ ret = NULL;
9521245 break;
9531246 }
9541247 }
....@@ -957,6 +1250,83 @@
9571250 return ret;
9581251 }
9591252
1253
+static void
1254
+nvmet_fc_portentry_bind(struct nvmet_fc_tgtport *tgtport,
1255
+ struct nvmet_fc_port_entry *pe,
1256
+ struct nvmet_port *port)
1257
+{
1258
+ lockdep_assert_held(&nvmet_fc_tgtlock);
1259
+
1260
+ pe->tgtport = tgtport;
1261
+ tgtport->pe = pe;
1262
+
1263
+ pe->port = port;
1264
+ port->priv = pe;
1265
+
1266
+ pe->node_name = tgtport->fc_target_port.node_name;
1267
+ pe->port_name = tgtport->fc_target_port.port_name;
1268
+ INIT_LIST_HEAD(&pe->pe_list);
1269
+
1270
+ list_add_tail(&pe->pe_list, &nvmet_fc_portentry_list);
1271
+}
1272
+
1273
+static void
1274
+nvmet_fc_portentry_unbind(struct nvmet_fc_port_entry *pe)
1275
+{
1276
+ unsigned long flags;
1277
+
1278
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
1279
+ if (pe->tgtport)
1280
+ pe->tgtport->pe = NULL;
1281
+ list_del(&pe->pe_list);
1282
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
1283
+}
1284
+
1285
+/*
1286
+ * called when a targetport deregisters. Breaks the relationship
1287
+ * with the nvmet port, but leaves the port_entry in place so that
1288
+ * re-registration can resume operation.
1289
+ */
1290
+static void
1291
+nvmet_fc_portentry_unbind_tgt(struct nvmet_fc_tgtport *tgtport)
1292
+{
1293
+ struct nvmet_fc_port_entry *pe;
1294
+ unsigned long flags;
1295
+
1296
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
1297
+ pe = tgtport->pe;
1298
+ if (pe)
1299
+ pe->tgtport = NULL;
1300
+ tgtport->pe = NULL;
1301
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
1302
+}
1303
+
1304
+/*
1305
+ * called when a new targetport is registered. Looks in the
1306
+ * existing nvmet port_entries to see if the nvmet layer is
1307
+ * configured for the targetport's wwn's. (the targetport existed,
1308
+ * nvmet configured, the lldd unregistered the tgtport, and is now
1309
+ * reregistering the same targetport). If so, set the nvmet port
1310
+ * port entry on the targetport.
1311
+ */
1312
+static void
1313
+nvmet_fc_portentry_rebind_tgt(struct nvmet_fc_tgtport *tgtport)
1314
+{
1315
+ struct nvmet_fc_port_entry *pe;
1316
+ unsigned long flags;
1317
+
1318
+ spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
1319
+ list_for_each_entry(pe, &nvmet_fc_portentry_list, pe_list) {
1320
+ if (tgtport->fc_target_port.node_name == pe->node_name &&
1321
+ tgtport->fc_target_port.port_name == pe->port_name) {
1322
+ WARN_ON(pe->tgtport);
1323
+ tgtport->pe = pe;
1324
+ pe->tgtport = tgtport;
1325
+ break;
1326
+ }
1327
+ }
1328
+ spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
1329
+}
9601330
9611331 /**
9621332 * nvme_fc_register_targetport - transport entry point called by an
....@@ -1014,16 +1384,21 @@
10141384
10151385 newrec->fc_target_port.node_name = pinfo->node_name;
10161386 newrec->fc_target_port.port_name = pinfo->port_name;
1017
- newrec->fc_target_port.private = &newrec[1];
1387
+ if (template->target_priv_sz)
1388
+ newrec->fc_target_port.private = &newrec[1];
1389
+ else
1390
+ newrec->fc_target_port.private = NULL;
10181391 newrec->fc_target_port.port_id = pinfo->port_id;
10191392 newrec->fc_target_port.port_num = idx;
10201393 INIT_LIST_HEAD(&newrec->tgt_list);
10211394 newrec->dev = dev;
10221395 newrec->ops = template;
10231396 spin_lock_init(&newrec->lock);
1024
- INIT_LIST_HEAD(&newrec->ls_list);
1397
+ INIT_LIST_HEAD(&newrec->ls_rcv_list);
1398
+ INIT_LIST_HEAD(&newrec->ls_req_list);
10251399 INIT_LIST_HEAD(&newrec->ls_busylist);
10261400 INIT_LIST_HEAD(&newrec->assoc_list);
1401
+ INIT_LIST_HEAD(&newrec->host_list);
10271402 kref_init(&newrec->ref);
10281403 ida_init(&newrec->assoc_cnt);
10291404 newrec->max_sg_cnt = template->max_sgl_segments;
....@@ -1033,6 +1408,8 @@
10331408 ret = -ENOMEM;
10341409 goto out_free_newrec;
10351410 }
1411
+
1412
+ nvmet_fc_portentry_rebind_tgt(newrec);
10361413
10371414 spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
10381415 list_add_tail(&newrec->tgt_list, &nvmet_fc_target_list);
....@@ -1104,13 +1481,72 @@
11041481 &tgtport->assoc_list, a_list) {
11051482 if (!nvmet_fc_tgt_a_get(assoc))
11061483 continue;
1107
- spin_unlock_irqrestore(&tgtport->lock, flags);
1108
- nvmet_fc_delete_target_assoc(assoc);
1109
- nvmet_fc_tgt_a_put(assoc);
1110
- spin_lock_irqsave(&tgtport->lock, flags);
1484
+ if (!schedule_work(&assoc->del_work))
1485
+ /* already deleting - release local reference */
1486
+ nvmet_fc_tgt_a_put(assoc);
11111487 }
11121488 spin_unlock_irqrestore(&tgtport->lock, flags);
11131489 }
1490
+
1491
+/**
1492
+ * nvmet_fc_invalidate_host - transport entry point called by an LLDD
1493
+ * to remove references to a hosthandle for LS's.
1494
+ *
1495
+ * The nvmet-fc layer ensures that any references to the hosthandle
1496
+ * on the targetport are forgotten (set to NULL). The LLDD will
1497
+ * typically call this when a login with a remote host port has been
1498
+ * lost, thus LS's for the remote host port are no longer possible.
1499
+ *
1500
+ * If an LS request is outstanding to the targetport/hosthandle (or
1501
+ * issued concurrently with the call to invalidate the host), the
1502
+ * LLDD is responsible for terminating/aborting the LS and completing
1503
+ * the LS request. It is recommended that these terminations/aborts
1504
+ * occur after calling to invalidate the host handle to avoid additional
1505
+ * retries by the nvmet-fc transport. The nvmet-fc transport may
1506
+ * continue to reference host handle while it cleans up outstanding
1507
+ * NVME associations. The nvmet-fc transport will call the
1508
+ * ops->host_release() callback to notify the LLDD that all references
1509
+ * are complete and the related host handle can be recovered.
1510
+ * Note: if there are no references, the callback may be called before
1511
+ * the invalidate host call returns.
1512
+ *
1513
+ * @target_port: pointer to the (registered) target port that a prior
1514
+ * LS was received on and which supplied the transport the
1515
+ * hosthandle.
1516
+ * @hosthandle: the handle (pointer) that represents the host port
1517
+ * that no longer has connectivity and that LS's should
1518
+ * no longer be directed to.
1519
+ */
1520
+void
1521
+nvmet_fc_invalidate_host(struct nvmet_fc_target_port *target_port,
1522
+ void *hosthandle)
1523
+{
1524
+ struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
1525
+ struct nvmet_fc_tgt_assoc *assoc, *next;
1526
+ unsigned long flags;
1527
+ bool noassoc = true;
1528
+
1529
+ spin_lock_irqsave(&tgtport->lock, flags);
1530
+ list_for_each_entry_safe(assoc, next,
1531
+ &tgtport->assoc_list, a_list) {
1532
+ if (!assoc->hostport ||
1533
+ assoc->hostport->hosthandle != hosthandle)
1534
+ continue;
1535
+ if (!nvmet_fc_tgt_a_get(assoc))
1536
+ continue;
1537
+ assoc->hostport->invalid = 1;
1538
+ noassoc = false;
1539
+ if (!schedule_work(&assoc->del_work))
1540
+ /* already deleting - release local reference */
1541
+ nvmet_fc_tgt_a_put(assoc);
1542
+ }
1543
+ spin_unlock_irqrestore(&tgtport->lock, flags);
1544
+
1545
+ /* if there's nothing to wait for - call the callback */
1546
+ if (noassoc && tgtport->ops->host_release)
1547
+ tgtport->ops->host_release(hosthandle);
1548
+}
1549
+EXPORT_SYMBOL_GPL(nvmet_fc_invalidate_host);
11141550
11151551 /*
11161552 * nvmet layer has called to terminate an association
....@@ -1146,7 +1582,9 @@
11461582 nvmet_fc_tgtport_put(tgtport);
11471583
11481584 if (found_ctrl) {
1149
- schedule_work(&assoc->del_work);
1585
+ if (!schedule_work(&assoc->del_work))
1586
+ /* already deleting - release local reference */
1587
+ nvmet_fc_tgt_a_put(assoc);
11501588 return;
11511589 }
11521590
....@@ -1159,8 +1597,8 @@
11591597 * nvme_fc_unregister_targetport - transport entry point called by an
11601598 * LLDD to deregister/remove a previously
11611599 * registered a local NVME subsystem FC port.
1162
- * @tgtport: pointer to the (registered) target port that is to be
1163
- * deregistered.
1600
+ * @target_port: pointer to the (registered) target port that is to be
1601
+ * deregistered.
11641602 *
11651603 * Returns:
11661604 * a completion status. Must be 0 upon success; a negative errno
....@@ -1171,8 +1609,17 @@
11711609 {
11721610 struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
11731611
1612
+ nvmet_fc_portentry_unbind_tgt(tgtport);
1613
+
11741614 /* terminate any outstanding associations */
11751615 __nvmet_fc_free_assocs(tgtport);
1616
+
1617
+ /*
1618
+ * should terminate LS's as well. However, LS's will be generated
1619
+ * at the tail end of association termination, so they likely don't
1620
+ * exist yet. And even if they did, it's worthwhile to just let
1621
+ * them finish and targetport ref counting will clean things up.
1622
+ */
11761623
11771624 nvmet_fc_tgtport_put(tgtport);
11781625
....@@ -1181,113 +1628,15 @@
11811628 EXPORT_SYMBOL_GPL(nvmet_fc_unregister_targetport);
11821629
11831630
1184
-/* *********************** FC-NVME LS Handling **************************** */
1631
+/* ********************** FC-NVME LS RCV Handling ************************* */
11851632
1186
-
1187
-static void
1188
-nvmet_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd)
1189
-{
1190
- struct fcnvme_ls_acc_hdr *acc = buf;
1191
-
1192
- acc->w0.ls_cmd = ls_cmd;
1193
- acc->desc_list_len = desc_len;
1194
- acc->rqst.desc_tag = cpu_to_be32(FCNVME_LSDESC_RQST);
1195
- acc->rqst.desc_len =
1196
- fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst));
1197
- acc->rqst.w0.ls_cmd = rqst_ls_cmd;
1198
-}
1199
-
1200
-static int
1201
-nvmet_fc_format_rjt(void *buf, u16 buflen, u8 ls_cmd,
1202
- u8 reason, u8 explanation, u8 vendor)
1203
-{
1204
- struct fcnvme_ls_rjt *rjt = buf;
1205
-
1206
- nvmet_fc_format_rsp_hdr(buf, FCNVME_LSDESC_RQST,
1207
- fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_rjt)),
1208
- ls_cmd);
1209
- rjt->rjt.desc_tag = cpu_to_be32(FCNVME_LSDESC_RJT);
1210
- rjt->rjt.desc_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rjt));
1211
- rjt->rjt.reason_code = reason;
1212
- rjt->rjt.reason_explanation = explanation;
1213
- rjt->rjt.vendor = vendor;
1214
-
1215
- return sizeof(struct fcnvme_ls_rjt);
1216
-}
1217
-
1218
-/* Validation Error indexes into the string table below */
1219
-enum {
1220
- VERR_NO_ERROR = 0,
1221
- VERR_CR_ASSOC_LEN = 1,
1222
- VERR_CR_ASSOC_RQST_LEN = 2,
1223
- VERR_CR_ASSOC_CMD = 3,
1224
- VERR_CR_ASSOC_CMD_LEN = 4,
1225
- VERR_ERSP_RATIO = 5,
1226
- VERR_ASSOC_ALLOC_FAIL = 6,
1227
- VERR_QUEUE_ALLOC_FAIL = 7,
1228
- VERR_CR_CONN_LEN = 8,
1229
- VERR_CR_CONN_RQST_LEN = 9,
1230
- VERR_ASSOC_ID = 10,
1231
- VERR_ASSOC_ID_LEN = 11,
1232
- VERR_NO_ASSOC = 12,
1233
- VERR_CONN_ID = 13,
1234
- VERR_CONN_ID_LEN = 14,
1235
- VERR_NO_CONN = 15,
1236
- VERR_CR_CONN_CMD = 16,
1237
- VERR_CR_CONN_CMD_LEN = 17,
1238
- VERR_DISCONN_LEN = 18,
1239
- VERR_DISCONN_RQST_LEN = 19,
1240
- VERR_DISCONN_CMD = 20,
1241
- VERR_DISCONN_CMD_LEN = 21,
1242
- VERR_DISCONN_SCOPE = 22,
1243
- VERR_RS_LEN = 23,
1244
- VERR_RS_RQST_LEN = 24,
1245
- VERR_RS_CMD = 25,
1246
- VERR_RS_CMD_LEN = 26,
1247
- VERR_RS_RCTL = 27,
1248
- VERR_RS_RO = 28,
1249
-};
1250
-
1251
-static char *validation_errors[] = {
1252
- "OK",
1253
- "Bad CR_ASSOC Length",
1254
- "Bad CR_ASSOC Rqst Length",
1255
- "Not CR_ASSOC Cmd",
1256
- "Bad CR_ASSOC Cmd Length",
1257
- "Bad Ersp Ratio",
1258
- "Association Allocation Failed",
1259
- "Queue Allocation Failed",
1260
- "Bad CR_CONN Length",
1261
- "Bad CR_CONN Rqst Length",
1262
- "Not Association ID",
1263
- "Bad Association ID Length",
1264
- "No Association",
1265
- "Not Connection ID",
1266
- "Bad Connection ID Length",
1267
- "No Connection",
1268
- "Not CR_CONN Cmd",
1269
- "Bad CR_CONN Cmd Length",
1270
- "Bad DISCONN Length",
1271
- "Bad DISCONN Rqst Length",
1272
- "Not DISCONN Cmd",
1273
- "Bad DISCONN Cmd Length",
1274
- "Bad Disconnect Scope",
1275
- "Bad RS Length",
1276
- "Bad RS Rqst Length",
1277
- "Not RS Cmd",
1278
- "Bad RS Cmd Length",
1279
- "Bad RS R_CTL",
1280
- "Bad RS Relative Offset",
1281
-};
12821633
12831634 static void
12841635 nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
12851636 struct nvmet_fc_ls_iod *iod)
12861637 {
1287
- struct fcnvme_ls_cr_assoc_rqst *rqst =
1288
- (struct fcnvme_ls_cr_assoc_rqst *)iod->rqstbuf;
1289
- struct fcnvme_ls_cr_assoc_acc *acc =
1290
- (struct fcnvme_ls_cr_assoc_acc *)iod->rspbuf;
1638
+ struct fcnvme_ls_cr_assoc_rqst *rqst = &iod->rqstbuf->rq_cr_assoc;
1639
+ struct fcnvme_ls_cr_assoc_acc *acc = &iod->rspbuf->rsp_cr_assoc;
12911640 struct nvmet_fc_tgt_queue *queue;
12921641 int ret = 0;
12931642
....@@ -1319,14 +1668,17 @@
13191668
13201669 else {
13211670 /* new association w/ admin queue */
1322
- iod->assoc = nvmet_fc_alloc_target_assoc(tgtport);
1671
+ iod->assoc = nvmet_fc_alloc_target_assoc(
1672
+ tgtport, iod->hosthandle);
13231673 if (!iod->assoc)
13241674 ret = VERR_ASSOC_ALLOC_FAIL;
13251675 else {
13261676 queue = nvmet_fc_alloc_target_queue(iod->assoc, 0,
13271677 be16_to_cpu(rqst->assoc_cmd.sqsize));
1328
- if (!queue)
1678
+ if (!queue) {
13291679 ret = VERR_QUEUE_ALLOC_FAIL;
1680
+ nvmet_fc_tgt_a_put(iod->assoc);
1681
+ }
13301682 }
13311683 }
13321684
....@@ -1334,8 +1686,8 @@
13341686 dev_err(tgtport->dev,
13351687 "Create Association LS failed: %s\n",
13361688 validation_errors[ret]);
1337
- iod->lsreq->rsplen = nvmet_fc_format_rjt(acc,
1338
- NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
1689
+ iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
1690
+ sizeof(*acc), rqst->w0.ls_cmd,
13391691 FCNVME_RJT_RC_LOGIC,
13401692 FCNVME_RJT_EXP_NONE, 0);
13411693 return;
....@@ -1345,11 +1697,15 @@
13451697 atomic_set(&queue->connected, 1);
13461698 queue->sqhd = 0; /* best place to init value */
13471699
1700
+ dev_info(tgtport->dev,
1701
+ "{%d:%d} Association created\n",
1702
+ tgtport->fc_target_port.port_num, iod->assoc->a_id);
1703
+
13481704 /* format a response */
13491705
1350
- iod->lsreq->rsplen = sizeof(*acc);
1706
+ iod->lsrsp->rsplen = sizeof(*acc);
13511707
1352
- nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
1708
+ nvme_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
13531709 fcnvme_lsdesc_len(
13541710 sizeof(struct fcnvme_ls_cr_assoc_acc)),
13551711 FCNVME_LS_CREATE_ASSOCIATION);
....@@ -1370,10 +1726,8 @@
13701726 nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
13711727 struct nvmet_fc_ls_iod *iod)
13721728 {
1373
- struct fcnvme_ls_cr_conn_rqst *rqst =
1374
- (struct fcnvme_ls_cr_conn_rqst *)iod->rqstbuf;
1375
- struct fcnvme_ls_cr_conn_acc *acc =
1376
- (struct fcnvme_ls_cr_conn_acc *)iod->rspbuf;
1729
+ struct fcnvme_ls_cr_conn_rqst *rqst = &iod->rqstbuf->rq_cr_conn;
1730
+ struct fcnvme_ls_cr_conn_acc *acc = &iod->rspbuf->rsp_cr_conn;
13771731 struct nvmet_fc_tgt_queue *queue;
13781732 int ret = 0;
13791733
....@@ -1425,8 +1779,8 @@
14251779 dev_err(tgtport->dev,
14261780 "Create Connection LS failed: %s\n",
14271781 validation_errors[ret]);
1428
- iod->lsreq->rsplen = nvmet_fc_format_rjt(acc,
1429
- NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
1782
+ iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
1783
+ sizeof(*acc), rqst->w0.ls_cmd,
14301784 (ret == VERR_NO_ASSOC) ?
14311785 FCNVME_RJT_RC_INV_ASSOC :
14321786 FCNVME_RJT_RC_LOGIC,
....@@ -1440,9 +1794,9 @@
14401794
14411795 /* format a response */
14421796
1443
- iod->lsreq->rsplen = sizeof(*acc);
1797
+ iod->lsrsp->rsplen = sizeof(*acc);
14441798
1445
- nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
1799
+ nvme_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
14461800 fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_cr_conn_acc)),
14471801 FCNVME_LS_CREATE_CONNECTION);
14481802 acc->connectid.desc_tag = cpu_to_be32(FCNVME_LSDESC_CONN_ID);
....@@ -1454,107 +1808,92 @@
14541808 be16_to_cpu(rqst->connect_cmd.qid)));
14551809 }
14561810
1457
-static void
1811
+/*
1812
+ * Returns true if the LS response is to be transmit
1813
+ * Returns false if the LS response is to be delayed
1814
+ */
1815
+static int
14581816 nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
14591817 struct nvmet_fc_ls_iod *iod)
14601818 {
1461
- struct fcnvme_ls_disconnect_rqst *rqst =
1462
- (struct fcnvme_ls_disconnect_rqst *)iod->rqstbuf;
1463
- struct fcnvme_ls_disconnect_acc *acc =
1464
- (struct fcnvme_ls_disconnect_acc *)iod->rspbuf;
1465
- struct nvmet_fc_tgt_queue *queue = NULL;
1466
- struct nvmet_fc_tgt_assoc *assoc;
1819
+ struct fcnvme_ls_disconnect_assoc_rqst *rqst =
1820
+ &iod->rqstbuf->rq_dis_assoc;
1821
+ struct fcnvme_ls_disconnect_assoc_acc *acc =
1822
+ &iod->rspbuf->rsp_dis_assoc;
1823
+ struct nvmet_fc_tgt_assoc *assoc = NULL;
1824
+ struct nvmet_fc_ls_iod *oldls = NULL;
1825
+ unsigned long flags;
14671826 int ret = 0;
1468
- bool del_assoc = false;
14691827
14701828 memset(acc, 0, sizeof(*acc));
14711829
1472
- if (iod->rqstdatalen < sizeof(struct fcnvme_ls_disconnect_rqst))
1473
- ret = VERR_DISCONN_LEN;
1474
- else if (rqst->desc_list_len !=
1475
- fcnvme_lsdesc_len(
1476
- sizeof(struct fcnvme_ls_disconnect_rqst)))
1477
- ret = VERR_DISCONN_RQST_LEN;
1478
- else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
1479
- ret = VERR_ASSOC_ID;
1480
- else if (rqst->associd.desc_len !=
1481
- fcnvme_lsdesc_len(
1482
- sizeof(struct fcnvme_lsdesc_assoc_id)))
1483
- ret = VERR_ASSOC_ID_LEN;
1484
- else if (rqst->discon_cmd.desc_tag !=
1485
- cpu_to_be32(FCNVME_LSDESC_DISCONN_CMD))
1486
- ret = VERR_DISCONN_CMD;
1487
- else if (rqst->discon_cmd.desc_len !=
1488
- fcnvme_lsdesc_len(
1489
- sizeof(struct fcnvme_lsdesc_disconn_cmd)))
1490
- ret = VERR_DISCONN_CMD_LEN;
1491
- else if ((rqst->discon_cmd.scope != FCNVME_DISCONN_ASSOCIATION) &&
1492
- (rqst->discon_cmd.scope != FCNVME_DISCONN_CONNECTION))
1493
- ret = VERR_DISCONN_SCOPE;
1494
- else {
1495
- /* match an active association */
1830
+ ret = nvmefc_vldt_lsreq_discon_assoc(iod->rqstdatalen, rqst);
1831
+ if (!ret) {
1832
+ /* match an active association - takes an assoc ref if !NULL */
14961833 assoc = nvmet_fc_find_target_assoc(tgtport,
14971834 be64_to_cpu(rqst->associd.association_id));
14981835 iod->assoc = assoc;
1499
- if (assoc) {
1500
- if (rqst->discon_cmd.scope ==
1501
- FCNVME_DISCONN_CONNECTION) {
1502
- queue = nvmet_fc_find_target_queue(tgtport,
1503
- be64_to_cpu(
1504
- rqst->discon_cmd.id));
1505
- if (!queue) {
1506
- nvmet_fc_tgt_a_put(assoc);
1507
- ret = VERR_NO_CONN;
1508
- }
1509
- }
1510
- } else
1836
+ if (!assoc)
15111837 ret = VERR_NO_ASSOC;
15121838 }
15131839
1514
- if (ret) {
1840
+ if (ret || !assoc) {
15151841 dev_err(tgtport->dev,
15161842 "Disconnect LS failed: %s\n",
15171843 validation_errors[ret]);
1518
- iod->lsreq->rsplen = nvmet_fc_format_rjt(acc,
1519
- NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
1844
+ iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
1845
+ sizeof(*acc), rqst->w0.ls_cmd,
15201846 (ret == VERR_NO_ASSOC) ?
15211847 FCNVME_RJT_RC_INV_ASSOC :
1522
- (ret == VERR_NO_CONN) ?
1523
- FCNVME_RJT_RC_INV_CONN :
1524
- FCNVME_RJT_RC_LOGIC,
1848
+ FCNVME_RJT_RC_LOGIC,
15251849 FCNVME_RJT_EXP_NONE, 0);
1526
- return;
1850
+ return true;
15271851 }
15281852
15291853 /* format a response */
15301854
1531
- iod->lsreq->rsplen = sizeof(*acc);
1855
+ iod->lsrsp->rsplen = sizeof(*acc);
15321856
1533
- nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
1857
+ nvme_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
15341858 fcnvme_lsdesc_len(
1535
- sizeof(struct fcnvme_ls_disconnect_acc)),
1536
- FCNVME_LS_DISCONNECT);
1537
-
1538
-
1539
- /* are we to delete a Connection ID (queue) */
1540
- if (queue) {
1541
- int qid = queue->qid;
1542
-
1543
- nvmet_fc_delete_target_queue(queue);
1544
-
1545
- /* release the get taken by find_target_queue */
1546
- nvmet_fc_tgt_q_put(queue);
1547
-
1548
- /* tear association down if io queue terminated */
1549
- if (!qid)
1550
- del_assoc = true;
1551
- }
1859
+ sizeof(struct fcnvme_ls_disconnect_assoc_acc)),
1860
+ FCNVME_LS_DISCONNECT_ASSOC);
15521861
15531862 /* release get taken in nvmet_fc_find_target_assoc */
1554
- nvmet_fc_tgt_a_put(iod->assoc);
1863
+ nvmet_fc_tgt_a_put(assoc);
15551864
1556
- if (del_assoc)
1557
- nvmet_fc_delete_target_assoc(iod->assoc);
1865
+ /*
1866
+ * The rules for LS response says the response cannot
1867
+ * go back until ABTS's have been sent for all outstanding
1868
+ * I/O and a Disconnect Association LS has been sent.
1869
+ * So... save off the Disconnect LS to send the response
1870
+ * later. If there was a prior LS already saved, replace
1871
+ * it with the newer one and send a can't perform reject
1872
+ * on the older one.
1873
+ */
1874
+ spin_lock_irqsave(&tgtport->lock, flags);
1875
+ oldls = assoc->rcv_disconn;
1876
+ assoc->rcv_disconn = iod;
1877
+ spin_unlock_irqrestore(&tgtport->lock, flags);
1878
+
1879
+ nvmet_fc_delete_target_assoc(assoc);
1880
+
1881
+ if (oldls) {
1882
+ dev_info(tgtport->dev,
1883
+ "{%d:%d} Multiple Disconnect Association LS's "
1884
+ "received\n",
1885
+ tgtport->fc_target_port.port_num, assoc->a_id);
1886
+ /* overwrite good response with bogus failure */
1887
+ oldls->lsrsp->rsplen = nvme_fc_format_rjt(oldls->rspbuf,
1888
+ sizeof(*iod->rspbuf),
1889
+ /* ok to use rqst, LS is same */
1890
+ rqst->w0.ls_cmd,
1891
+ FCNVME_RJT_RC_UNAB,
1892
+ FCNVME_RJT_EXP_NONE, 0);
1893
+ nvmet_fc_xmt_ls_rsp(tgtport, oldls);
1894
+ }
1895
+
1896
+ return false;
15581897 }
15591898
15601899
....@@ -1566,13 +1905,13 @@
15661905 static const struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops;
15671906
15681907 static void
1569
-nvmet_fc_xmt_ls_rsp_done(struct nvmefc_tgt_ls_req *lsreq)
1908
+nvmet_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
15701909 {
1571
- struct nvmet_fc_ls_iod *iod = lsreq->nvmet_fc_private;
1910
+ struct nvmet_fc_ls_iod *iod = lsrsp->nvme_fc_private;
15721911 struct nvmet_fc_tgtport *tgtport = iod->tgtport;
15731912
15741913 fc_dma_sync_single_for_cpu(tgtport->dev, iod->rspdma,
1575
- NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
1914
+ sizeof(*iod->rspbuf), DMA_TO_DEVICE);
15761915 nvmet_fc_free_ls_iod(tgtport, iod);
15771916 nvmet_fc_tgtport_put(tgtport);
15781917 }
....@@ -1584,11 +1923,11 @@
15841923 int ret;
15851924
15861925 fc_dma_sync_single_for_device(tgtport->dev, iod->rspdma,
1587
- NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
1926
+ sizeof(*iod->rspbuf), DMA_TO_DEVICE);
15881927
1589
- ret = tgtport->ops->xmt_ls_rsp(&tgtport->fc_target_port, iod->lsreq);
1928
+ ret = tgtport->ops->xmt_ls_rsp(&tgtport->fc_target_port, iod->lsrsp);
15901929 if (ret)
1591
- nvmet_fc_xmt_ls_rsp_done(iod->lsreq);
1930
+ nvmet_fc_xmt_ls_rsp_done(iod->lsrsp);
15921931 }
15931932
15941933 /*
....@@ -1598,15 +1937,15 @@
15981937 nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
15991938 struct nvmet_fc_ls_iod *iod)
16001939 {
1601
- struct fcnvme_ls_rqst_w0 *w0 =
1602
- (struct fcnvme_ls_rqst_w0 *)iod->rqstbuf;
1940
+ struct fcnvme_ls_rqst_w0 *w0 = &iod->rqstbuf->rq_cr_assoc.w0;
1941
+ bool sendrsp = true;
16031942
1604
- iod->lsreq->nvmet_fc_private = iod;
1605
- iod->lsreq->rspbuf = iod->rspbuf;
1606
- iod->lsreq->rspdma = iod->rspdma;
1607
- iod->lsreq->done = nvmet_fc_xmt_ls_rsp_done;
1943
+ iod->lsrsp->nvme_fc_private = iod;
1944
+ iod->lsrsp->rspbuf = iod->rspbuf;
1945
+ iod->lsrsp->rspdma = iod->rspdma;
1946
+ iod->lsrsp->done = nvmet_fc_xmt_ls_rsp_done;
16081947 /* Be preventative. handlers will later set to valid length */
1609
- iod->lsreq->rsplen = 0;
1948
+ iod->lsrsp->rsplen = 0;
16101949
16111950 iod->assoc = NULL;
16121951
....@@ -1624,17 +1963,18 @@
16241963 /* Creates an IO Queue/Connection */
16251964 nvmet_fc_ls_create_connection(tgtport, iod);
16261965 break;
1627
- case FCNVME_LS_DISCONNECT:
1966
+ case FCNVME_LS_DISCONNECT_ASSOC:
16281967 /* Terminate a Queue/Connection or the Association */
1629
- nvmet_fc_ls_disconnect(tgtport, iod);
1968
+ sendrsp = nvmet_fc_ls_disconnect(tgtport, iod);
16301969 break;
16311970 default:
1632
- iod->lsreq->rsplen = nvmet_fc_format_rjt(iod->rspbuf,
1633
- NVME_FC_MAX_LS_BUFFER_SIZE, w0->ls_cmd,
1971
+ iod->lsrsp->rsplen = nvme_fc_format_rjt(iod->rspbuf,
1972
+ sizeof(*iod->rspbuf), w0->ls_cmd,
16341973 FCNVME_RJT_RC_INVAL, FCNVME_RJT_EXP_NONE, 0);
16351974 }
16361975
1637
- nvmet_fc_xmt_ls_rsp(tgtport, iod);
1976
+ if (sendrsp)
1977
+ nvmet_fc_xmt_ls_rsp(tgtport, iod);
16381978 }
16391979
16401980 /*
....@@ -1661,37 +2001,55 @@
16612001 *
16622002 * If this routine returns error, the LLDD should abort the exchange.
16632003 *
1664
- * @tgtport: pointer to the (registered) target port the LS was
2004
+ * @target_port: pointer to the (registered) target port the LS was
16652005 * received on.
1666
- * @lsreq: pointer to a lsreq request structure to be used to reference
2006
+ * @lsrsp: pointer to a lsrsp structure to be used to reference
16672007 * the exchange corresponding to the LS.
16682008 * @lsreqbuf: pointer to the buffer containing the LS Request
16692009 * @lsreqbuf_len: length, in bytes, of the received LS request
16702010 */
16712011 int
16722012 nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port,
1673
- struct nvmefc_tgt_ls_req *lsreq,
2013
+ void *hosthandle,
2014
+ struct nvmefc_ls_rsp *lsrsp,
16742015 void *lsreqbuf, u32 lsreqbuf_len)
16752016 {
16762017 struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
16772018 struct nvmet_fc_ls_iod *iod;
2019
+ struct fcnvme_ls_rqst_w0 *w0 = (struct fcnvme_ls_rqst_w0 *)lsreqbuf;
16782020
1679
- if (lsreqbuf_len > NVME_FC_MAX_LS_BUFFER_SIZE)
2021
+ if (lsreqbuf_len > sizeof(union nvmefc_ls_requests)) {
2022
+ dev_info(tgtport->dev,
2023
+ "RCV %s LS failed: payload too large (%d)\n",
2024
+ (w0->ls_cmd <= NVME_FC_LAST_LS_CMD_VALUE) ?
2025
+ nvmefc_ls_names[w0->ls_cmd] : "",
2026
+ lsreqbuf_len);
16802027 return -E2BIG;
2028
+ }
16812029
1682
- if (!nvmet_fc_tgtport_get(tgtport))
2030
+ if (!nvmet_fc_tgtport_get(tgtport)) {
2031
+ dev_info(tgtport->dev,
2032
+ "RCV %s LS failed: target deleting\n",
2033
+ (w0->ls_cmd <= NVME_FC_LAST_LS_CMD_VALUE) ?
2034
+ nvmefc_ls_names[w0->ls_cmd] : "");
16832035 return -ESHUTDOWN;
2036
+ }
16842037
16852038 iod = nvmet_fc_alloc_ls_iod(tgtport);
16862039 if (!iod) {
2040
+ dev_info(tgtport->dev,
2041
+ "RCV %s LS failed: context allocation failed\n",
2042
+ (w0->ls_cmd <= NVME_FC_LAST_LS_CMD_VALUE) ?
2043
+ nvmefc_ls_names[w0->ls_cmd] : "");
16872044 nvmet_fc_tgtport_put(tgtport);
16882045 return -ENOENT;
16892046 }
16902047
1691
- iod->lsreq = lsreq;
2048
+ iod->lsrsp = lsrsp;
16922049 iod->fcpreq = NULL;
16932050 memcpy(iod->rqstbuf, lsreqbuf, lsreqbuf_len);
16942051 iod->rqstdatalen = lsreqbuf_len;
2052
+ iod->hosthandle = hosthandle;
16952053
16962054 schedule_work(&iod->work);
16972055
....@@ -1798,7 +2156,7 @@
17982156 */
17992157 rspcnt = atomic_inc_return(&fod->queue->zrspcnt);
18002158 if (!(rspcnt % fod->queue->ersp_ratio) ||
1801
- sqe->opcode == nvme_fabrics_command ||
2159
+ nvme_is_fabrics((struct nvme_command *) sqe) ||
18022160 xfr_length != fod->req.transfer_len ||
18032161 (le16_to_cpu(cqe->status) & 0xFFFE) || cqewd[0] || cqewd[1] ||
18042162 (sqe->flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND)) ||
....@@ -2007,7 +2365,7 @@
20072365 }
20082366
20092367 /* data transfer complete, resume with nvmet layer */
2010
- nvmet_req_execute(&fod->req);
2368
+ fod->req.execute(&fod->req);
20112369 break;
20122370
20132371 case NVMET_FCOP_READDATA:
....@@ -2058,25 +2416,11 @@
20582416 }
20592417
20602418 static void
2061
-nvmet_fc_fcp_rqst_op_done_work(struct work_struct *work)
2062
-{
2063
- struct nvmet_fc_fcp_iod *fod =
2064
- container_of(work, struct nvmet_fc_fcp_iod, done_work);
2065
-
2066
- nvmet_fc_fod_op_done(fod);
2067
-}
2068
-
2069
-static void
20702419 nvmet_fc_xmt_fcp_op_done(struct nvmefc_tgt_fcp_req *fcpreq)
20712420 {
20722421 struct nvmet_fc_fcp_iod *fod = fcpreq->nvmet_fc_private;
2073
- struct nvmet_fc_tgt_queue *queue = fod->queue;
20742422
2075
- if (fod->tgtport->ops->target_features & NVMET_FCTGTFEAT_OPDONE_IN_ISR)
2076
- /* context switch so completion is not in ISR context */
2077
- queue_work_on(queue->cpu, queue->work_q, &fod->done_work);
2078
- else
2079
- nvmet_fc_fod_op_done(fod);
2423
+ nvmet_fc_fod_op_done(fod);
20802424 }
20812425
20822426 /*
....@@ -2147,7 +2491,7 @@
21472491
21482492
21492493 /*
2150
- * Actual processing routine for received FC-NVME LS Requests from the LLD
2494
+ * Actual processing routine for received FC-NVME I/O Requests from the LLD
21512495 */
21522496 static void
21532497 nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
....@@ -2183,8 +2527,9 @@
21832527 }
21842528
21852529 fod->req.cmd = &fod->cmdiubuf.sqe;
2186
- fod->req.rsp = &fod->rspiubuf.cqe;
2187
- fod->req.port = fod->queue->port;
2530
+ fod->req.cqe = &fod->rspiubuf.cqe;
2531
+ if (tgtport->pe)
2532
+ fod->req.port = tgtport->pe->port;
21882533
21892534 /* clear any response payload */
21902535 memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf));
....@@ -2230,24 +2575,11 @@
22302575 * can invoke the nvmet_layer now. If read data, cmd completion will
22312576 * push the data
22322577 */
2233
- nvmet_req_execute(&fod->req);
2578
+ fod->req.execute(&fod->req);
22342579 return;
22352580
22362581 transport_error:
22372582 nvmet_fc_abort_op(tgtport, fod);
2238
-}
2239
-
2240
-/*
2241
- * Actual processing routine for received FC-NVME LS Requests from the LLD
2242
- */
2243
-static void
2244
-nvmet_fc_handle_fcp_rqst_work(struct work_struct *work)
2245
-{
2246
- struct nvmet_fc_fcp_iod *fod =
2247
- container_of(work, struct nvmet_fc_fcp_iod, work);
2248
- struct nvmet_fc_tgtport *tgtport = fod->tgtport;
2249
-
2250
- nvmet_fc_handle_fcp_rqst(tgtport, fod);
22512583 }
22522584
22532585 /**
....@@ -2311,7 +2643,7 @@
23112643
23122644 /* validate iu, so the connection id can be used to find the queue */
23132645 if ((cmdiubuf_len != sizeof(*cmdiu)) ||
2314
- (cmdiu->scsi_id != NVME_CMD_SCSI_ID) ||
2646
+ (cmdiu->format_id != NVME_CMD_FORMAT_ID) ||
23152647 (cmdiu->fc_id != NVME_CMD_FC_ID) ||
23162648 (be16_to_cpu(cmdiu->iu_len) != (sizeof(*cmdiu)/4)))
23172649 return -EIO;
....@@ -2468,7 +2800,7 @@
24682800 substring_t wwn = { name, &name[sizeof(name)-1] };
24692801 int nnoffset, pnoffset;
24702802
2471
- /* validate it string one of the 2 allowed formats */
2803
+ /* validate if string is one of the 2 allowed formats */
24722804 if (strnlen(buf, blen) == NVME_FC_TRADDR_MAXLENGTH &&
24732805 !strncmp(buf, "nn-0x", NVME_FC_TRADDR_OXNNLEN) &&
24742806 !strncmp(&buf[NVME_FC_TRADDR_MAX_PN_OFFSET],
....@@ -2508,6 +2840,7 @@
25082840 nvmet_fc_add_port(struct nvmet_port *port)
25092841 {
25102842 struct nvmet_fc_tgtport *tgtport;
2843
+ struct nvmet_fc_port_entry *pe;
25112844 struct nvmet_fc_traddr traddr = { 0L, 0L };
25122845 unsigned long flags;
25132846 int ret;
....@@ -2524,24 +2857,50 @@
25242857 if (ret)
25252858 return ret;
25262859
2860
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
2861
+ if (!pe)
2862
+ return -ENOMEM;
2863
+
25272864 ret = -ENXIO;
25282865 spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
25292866 list_for_each_entry(tgtport, &nvmet_fc_target_list, tgt_list) {
25302867 if ((tgtport->fc_target_port.node_name == traddr.nn) &&
25312868 (tgtport->fc_target_port.port_name == traddr.pn)) {
2532
- tgtport->port = port;
2533
- ret = 0;
2869
+ /* a FC port can only be 1 nvmet port id */
2870
+ if (!tgtport->pe) {
2871
+ nvmet_fc_portentry_bind(tgtport, pe, port);
2872
+ ret = 0;
2873
+ } else
2874
+ ret = -EALREADY;
25342875 break;
25352876 }
25362877 }
25372878 spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
2879
+
2880
+ if (ret)
2881
+ kfree(pe);
2882
+
25382883 return ret;
25392884 }
25402885
25412886 static void
25422887 nvmet_fc_remove_port(struct nvmet_port *port)
25432888 {
2544
- /* nothing to do */
2889
+ struct nvmet_fc_port_entry *pe = port->priv;
2890
+
2891
+ nvmet_fc_portentry_unbind(pe);
2892
+
2893
+ kfree(pe);
2894
+}
2895
+
2896
+static void
2897
+nvmet_fc_discovery_chg(struct nvmet_port *port)
2898
+{
2899
+ struct nvmet_fc_port_entry *pe = port->priv;
2900
+ struct nvmet_fc_tgtport *tgtport = pe->tgtport;
2901
+
2902
+ if (tgtport && tgtport->ops->discovery_event)
2903
+ tgtport->ops->discovery_event(&tgtport->fc_target_port);
25452904 }
25462905
25472906 static const struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = {
....@@ -2552,6 +2911,7 @@
25522911 .remove_port = nvmet_fc_remove_port,
25532912 .queue_response = nvmet_fc_fcp_nvme_cmd_done,
25542913 .delete_ctrl = nvmet_fc_delete_ctrl,
2914
+ .discovery_chg = nvmet_fc_discovery_chg,
25552915 };
25562916
25572917 static int __init nvmet_fc_init_module(void)