diff options
author | James Smart <jsmart2021@gmail.com> | 2017-04-11 20:35:09 +0200 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2017-04-21 16:41:53 +0200 |
commit | 8d64daf7dcd851b249717ac88e2d4989f9ad2467 (patch) | |
tree | 050e9b0f0406f5e2a616d7461c3a76a3bd794547 | |
parent | nvme_fc: Move LS's to rport (diff) | |
download | linux-8d64daf7dcd851b249717ac88e2d4989f9ad2467.tar.xz linux-8d64daf7dcd851b249717ac88e2d4989f9ad2467.zip |
nvme_fc: Add ls aborts on remote port teardown
remoteport teardown never aborted the LS opertions. Add support.
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
-rw-r--r-- | drivers/nvme/host/fc.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index a0c5e5420c41..596b3a453b54 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -61,12 +61,19 @@ struct nvme_fc_queue { unsigned long flags; } __aligned(sizeof(u64)); /* alignment for other things alloc'd with */ +enum nvme_fcop_flags { + FCOP_FLAGS_TERMIO = (1 << 0), + FCOP_FLAGS_RELEASED = (1 << 1), + FCOP_FLAGS_COMPLETE = (1 << 2), +}; + struct nvmefc_ls_req_op { struct nvmefc_ls_req ls_req; struct nvme_fc_rport *rport; struct nvme_fc_queue *queue; struct request *rq; + u32 flags; int ls_error; struct completion ls_done; @@ -491,6 +498,30 @@ nvme_fc_rport_get(struct nvme_fc_rport *rport) return kref_get_unless_zero(&rport->ref); } +static int +nvme_fc_abort_lsops(struct nvme_fc_rport *rport) +{ + struct nvmefc_ls_req_op *lsop; + unsigned long flags; + +restart: + spin_lock_irqsave(&rport->lock, flags); + + list_for_each_entry(lsop, &rport->ls_req_list, lsreq_list) { + if (!(lsop->flags & FCOP_FLAGS_TERMIO)) { + lsop->flags |= FCOP_FLAGS_TERMIO; + spin_unlock_irqrestore(&rport->lock, flags); + rport->lport->ops->ls_abort(&rport->lport->localport, + &rport->remoteport, + &lsop->ls_req); + goto restart; + } + } + spin_unlock_irqrestore(&rport->lock, flags); + + return 0; +} + /** * nvme_fc_unregister_remoteport - transport entry point called by an * LLDD to deregister/remove a previously @@ -526,6 +557,8 @@ nvme_fc_unregister_remoteport(struct nvme_fc_remote_port *portptr) spin_unlock_irqrestore(&rport->lock, flags); + nvme_fc_abort_lsops(rport); + nvme_fc_rport_put(rport); return 0; } |