Pull NVMe fixes from Keith * 'nvme/for-5.5' of git://git.infradead.org/nvme: nvme/pci: Fix read queue count nvme/pci Limit write queue sizes to possible cpus nvme/pci: Fix write and poll queue types nvme/pci: Remove last_cq_head nvme: Namepace identification descriptor list is optional nvme-fc: fix double-free scenarios on hw queues nvme: else following return is not needed nvme: add error message on mismatching controller ids nvme_fc: add module to ops template to allow module references nvmet-loop: Avoid preallocating big SGL for data nvme-fc: Avoid preallocating big SGL for data nvme-rdma: Avoid preallocating big SGL for data
Unified · Split
| @@ -1735,6 +1735,8 @@ static int nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid, · 1734 unmodified lines | ||
| 1735 | 1735 | if (ret) |
| 1736 | 1736 | dev_warn(ctrl->device, |
| 1737 | 1737 | "Identify Descriptors failed (%d)\n", ret); |
| 1738 | + if (ret > 0) | |
| 1739 | + ret = 0; | |
| 1738 | 1740 | } |
| 1739 | 1741 | return ret; |
| 1740 | 1742 | } |
| @@ -2862,6 +2864,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) · 1121 unmodified lines | ||
| 2862 | 2864 | * admin connect |
| 2863 | 2865 | */ |
| 2864 | 2866 | if (ctrl->cntlid != le16_to_cpu(id->cntlid)) { |
| 2867 | + dev_err(ctrl->device, | |
| 2868 | + "Mismatching cntlid: Connect %u vs Identify " | |
| 2869 | + "%u, rejecting\n", | |
| 2870 | + ctrl->cntlid, le16_to_cpu(id->cntlid)); | |
| 2865 | 2871 | ret = -EINVAL; |
| 2866 | 2872 | goto out_free; |
| 2867 | 2873 | } |
| @@ -95,7 +95,7 @@ struct nvme_fc_fcp_op { · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | struct nvme_fcp_op_w_sgl { |
| 97 | 97 | struct nvme_fc_fcp_op op; |
| 98 | − struct scatterlist sgl[SG_CHUNK_SIZE]; | |
| 98 | + struct scatterlist sgl[NVME_INLINE_SG_CNT]; | |
| 99 | 99 | uint8_t priv[0]; |
| 100 | 100 | }; |
| 101 | 101 | |
| @@ -342,7 +342,8 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo, · 240 unmodified lines | ||
| 342 | 342 | !template->ls_req || !template->fcp_io || |
| 343 | 343 | !template->ls_abort || !template->fcp_abort || |
| 344 | 344 | !template->max_hw_queues || !template->max_sgl_segments || |
| 345 | − !template->max_dif_sgl_segments || !template->dma_boundary) { | |
| 345 | + !template->max_dif_sgl_segments || !template->dma_boundary || | |
| 346 | + !template->module) { | |
| 346 | 347 | ret = -EINVAL; |
| 347 | 348 | goto out_reghost_failed; |
| 348 | 349 | } |
| @@ -2015,6 +2016,7 @@ nvme_fc_ctrl_free(struct kref *ref) · 1666 unmodified lines | ||
| 2015 | 2016 | { |
| 2016 | 2017 | struct nvme_fc_ctrl *ctrl = |
| 2017 | 2018 | container_of(ref, struct nvme_fc_ctrl, ref); |
| 2019 | + struct nvme_fc_lport *lport = ctrl->lport; | |
| 2018 | 2020 | unsigned long flags; |
| 2019 | 2021 | |
| 2020 | 2022 | if (ctrl->ctrl.tagset) { |
| @@ -2041,6 +2043,7 @@ nvme_fc_ctrl_free(struct kref *ref) · 20 unmodified lines | ||
| 2041 | 2043 | if (ctrl->ctrl.opts) |
| 2042 | 2044 | nvmf_free_options(ctrl->ctrl.opts); |
| 2043 | 2045 | kfree(ctrl); |
| 2046 | + module_put(lport->ops->module); | |
| 2044 | 2047 | } |
| 2045 | 2048 | |
| 2046 | 2049 | static void |
| @@ -2141,7 +2144,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq, · 94 unmodified lines | ||
| 2141 | 2144 | freq->sg_table.sgl = freq->first_sgl; |
| 2142 | 2145 | ret = sg_alloc_table_chained(&freq->sg_table, |
| 2143 | 2146 | blk_rq_nr_phys_segments(rq), freq->sg_table.sgl, |
| 2144 | − SG_CHUNK_SIZE); | |
| 2147 | + NVME_INLINE_SG_CNT); | |
| 2145 | 2148 | if (ret) |
| 2146 | 2149 | return -ENOMEM; |
| 2147 | 2150 | |
| @@ -2150,7 +2153,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq, · 2 unmodified lines | ||
| 2150 | 2153 | freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl, |
| 2151 | 2154 | op->nents, rq_dma_dir(rq)); |
| 2152 | 2155 | if (unlikely(freq->sg_cnt <= 0)) { |
| 2153 | − sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE); | |
| 2156 | + sg_free_table_chained(&freq->sg_table, NVME_INLINE_SG_CNT); | |
| 2154 | 2157 | freq->sg_cnt = 0; |
| 2155 | 2158 | return -EFAULT; |
| 2156 | 2159 | } |
| @@ -2173,7 +2176,7 @@ nvme_fc_unmap_data(struct nvme_fc_ctrl *ctrl, struct request *rq, · 16 unmodified lines | ||
| 2173 | 2176 | fc_dma_unmap_sg(ctrl->lport->dev, freq->sg_table.sgl, op->nents, |
| 2174 | 2177 | rq_dma_dir(rq)); |
| 2175 | 2178 | |
| 2176 | − sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE); | |
| 2179 | + sg_free_table_chained(&freq->sg_table, NVME_INLINE_SG_CNT); | |
| 2177 | 2180 | |
| 2178 | 2181 | freq->sg_cnt = 0; |
| 2179 | 2182 | } |
| @@ -2910,10 +2913,22 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status) · 730 unmodified lines | ||
| 2910 | 2913 | static void |
| 2911 | 2914 | __nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl) |
| 2912 | 2915 | { |
| 2913 | − nvme_stop_keep_alive(&ctrl->ctrl); | |
| 2916 | + /* | |
| 2917 | + * if state is connecting - the error occurred as part of a | |
| 2918 | + * reconnect attempt. The create_association error paths will | |
| 2919 | + * clean up any outstanding io. | |
| 2920 | + * | |
| 2921 | + * if it's a different state - ensure all pending io is | |
| 2922 | + * terminated. Given this can delay while waiting for the | |
| 2923 | + * aborted io to return, we recheck adapter state below | |
| 2924 | + * before changing state. | |
| 2925 | + */ | |
| 2926 | + if (ctrl->ctrl.state != NVME_CTRL_CONNECTING) { | |
| 2927 | + nvme_stop_keep_alive(&ctrl->ctrl); | |
| 2914 | 2928 | |
| 2915 | − /* will block will waiting for io to terminate */ | |
| 2916 | − nvme_fc_delete_association(ctrl); | |
| 2929 | + /* will block will waiting for io to terminate */ | |
| 2930 | + nvme_fc_delete_association(ctrl); | |
| 2931 | + } | |
| 2917 | 2932 | |
| 2918 | 2933 | if (ctrl->ctrl.state != NVME_CTRL_CONNECTING && |
| 2919 | 2934 | !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) |
| @@ -3059,10 +3074,15 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, · 139 unmodified lines | ||
| 3059 | 3074 | goto out_fail; |
| 3060 | 3075 | } |
| 3061 | 3076 | |
| 3077 | + if (!try_module_get(lport->ops->module)) { | |
| 3078 | + ret = -EUNATCH; | |
| 3079 | + goto out_free_ctrl; | |
| 3080 | + } | |
| 3081 | + | |
| 3062 | 3082 | idx = ida_simple_get(&nvme_fc_ctrl_cnt, 0, 0, GFP_KERNEL); |
| 3063 | 3083 | if (idx < 0) { |
| 3064 | 3084 | ret = -ENOSPC; |
| 3065 | − goto out_free_ctrl; | |
| 3085 | + goto out_mod_put; | |
| 3066 | 3086 | } |
| 3067 | 3087 | |
| 3068 | 3088 | ctrl->ctrl.opts = opts; |
| @@ -3215,6 +3235,8 @@ out_free_queues: · 146 unmodified lines | ||
| 3215 | 3235 | out_free_ida: |
| 3216 | 3236 | put_device(ctrl->dev); |
| 3217 | 3237 | ida_simple_remove(&nvme_fc_ctrl_cnt, ctrl->cnum); |
| 3238 | +out_mod_put: | |
| 3239 | + module_put(lport->ops->module); | |
| 3218 | 3240 | out_free_ctrl: |
| 3219 | 3241 | kfree(ctrl); |
| 3220 | 3242 | out_fail: |
| @@ -28,6 +28,12 @@ extern unsigned int admin_timeout; · 27 unmodified lines | ||
| 28 | 28 | #define NVME_DEFAULT_KATO 5 |
| 29 | 29 | #define NVME_KATO_GRACE 10 |
| 30 | 30 | |
| 31 | +#ifdef CONFIG_ARCH_NO_SG_CHAIN | |
| 32 | +#define NVME_INLINE_SG_CNT 0 | |
| 33 | +#else | |
| 34 | +#define NVME_INLINE_SG_CNT 2 | |
| 35 | +#endif | |
| 36 | + | |
| 31 | 37 | extern struct workqueue_struct *nvme_wq; |
| 32 | 38 | extern struct workqueue_struct *nvme_reset_wq; |
| 33 | 39 | extern struct workqueue_struct *nvme_delete_wq; |
| @@ -68,14 +68,14 @@ static int io_queue_depth = 1024; · 67 unmodified lines | ||
| 68 | 68 | module_param_cb(io_queue_depth, &io_queue_depth_ops, &io_queue_depth, 0644); |
| 69 | 69 | MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2"); |
| 70 | 70 | |
| 71 | −static int write_queues; | |
| 72 | −module_param(write_queues, int, 0644); | |
| 71 | +static unsigned int write_queues; | |
| 72 | +module_param(write_queues, uint, 0644); | |
| 73 | 73 | MODULE_PARM_DESC(write_queues, |
| 74 | 74 | "Number of queues to use for writes. If not set, reads and writes " |
| 75 | 75 | "will share a queue set."); |
| 76 | 76 | |
| 77 | −static int poll_queues; | |
| 78 | −module_param(poll_queues, int, 0644); | |
| 77 | +static unsigned int poll_queues; | |
| 78 | +module_param(poll_queues, uint, 0644); | |
| 79 | 79 | MODULE_PARM_DESC(poll_queues, "Number of queues to use for polled IO."); |
| 80 | 80 | |
| 81 | 81 | struct nvme_dev; |
| @@ -176,7 +176,6 @@ struct nvme_queue { · 94 unmodified lines | ||
| 176 | 176 | u16 sq_tail; |
| 177 | 177 | u16 last_sq_tail; |
| 178 | 178 | u16 cq_head; |
| 179 | − u16 last_cq_head; | |
| 180 | 179 | u16 qid; |
| 181 | 180 | u8 cq_phase; |
| 182 | 181 | u8 sqes; |
| @@ -1026,10 +1025,7 @@ static irqreturn_t nvme_irq(int irq, void *data) · 843 unmodified lines | ||
| 1026 | 1025 | * the irq handler, even if that was on another CPU. |
| 1027 | 1026 | */ |
| 1028 | 1027 | rmb(); |
| 1029 | − if (nvmeq->cq_head != nvmeq->last_cq_head) | |
| 1030 | − ret = IRQ_HANDLED; | |
| 1031 | 1028 | nvme_process_cq(nvmeq, &start, &end, -1); |
| 1032 | − nvmeq->last_cq_head = nvmeq->cq_head; | |
| 1033 | 1029 | wmb(); |
| 1034 | 1030 | |
| 1035 | 1031 | if (start != end) { |
| @@ -1549,7 +1545,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled) · 513 unmodified lines | ||
| 1549 | 1545 | result = adapter_alloc_sq(dev, qid, nvmeq); |
| 1550 | 1546 | if (result < 0) |
| 1551 | 1547 | return result; |
| 1552 | − else if (result) | |
| 1548 | + if (result) | |
| 1553 | 1549 | goto release_cq; |
| 1554 | 1550 | |
| 1555 | 1551 | nvmeq->cq_vector = vector; |
| @@ -2058,7 +2054,6 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) · 502 unmodified lines | ||
| 2058 | 2054 | .priv = dev, |
| 2059 | 2055 | }; |
| 2060 | 2056 | unsigned int irq_queues, this_p_queues; |
| 2061 | − unsigned int nr_cpus = num_possible_cpus(); | |
| 2062 | 2057 | |
| 2063 | 2058 | /* |
| 2064 | 2059 | * Poll queues don't need interrupts, but we need at least one IO |
| @@ -2069,10 +2064,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) · 4 unmodified lines | ||
| 2069 | 2064 | this_p_queues = nr_io_queues - 1; |
| 2070 | 2065 | irq_queues = 1; |
| 2071 | 2066 | } else { |
| 2072 | − if (nr_cpus < nr_io_queues - this_p_queues) | |
| 2073 | − irq_queues = nr_cpus + 1; | |
| 2074 | − else | |
| 2075 | − irq_queues = nr_io_queues - this_p_queues + 1; | |
| 2067 | + irq_queues = nr_io_queues - this_p_queues + 1; | |
| 2076 | 2068 | } |
| 2077 | 2069 | dev->io_queues[HCTX_TYPE_POLL] = this_p_queues; |
| 2078 | 2070 | |
| @@ -3142,6 +3134,9 @@ static int __init nvme_init(void) · 1063 unmodified lines | ||
| 3142 | 3134 | BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64); |
| 3143 | 3135 | BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64); |
| 3144 | 3136 | BUILD_BUG_ON(IRQ_AFFINITY_MAX_SETS < 2); |
| 3137 | + | |
| 3138 | + write_queues = min(write_queues, num_possible_cpus()); | |
| 3139 | + poll_queues = min(poll_queues, num_possible_cpus()); | |
| 3145 | 3140 | return pci_register_driver(&nvme_driver); |
| 3146 | 3141 | } |
| 3147 | 3142 | |
| @@ -731,7 +731,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl, · 730 unmodified lines | ||
| 731 | 731 | set->reserved_tags = 2; /* connect + keep-alive */ |
| 732 | 732 | set->numa_node = nctrl->numa_node; |
| 733 | 733 | set->cmd_size = sizeof(struct nvme_rdma_request) + |
| 734 | − SG_CHUNK_SIZE * sizeof(struct scatterlist); | |
| 734 | + NVME_INLINE_SG_CNT * sizeof(struct scatterlist); | |
| 735 | 735 | set->driver_data = ctrl; |
| 736 | 736 | set->nr_hw_queues = 1; |
| 737 | 737 | set->timeout = ADMIN_TIMEOUT; |
| @@ -745,7 +745,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl, · 7 unmodified lines | ||
| 745 | 745 | set->numa_node = nctrl->numa_node; |
| 746 | 746 | set->flags = BLK_MQ_F_SHOULD_MERGE; |
| 747 | 747 | set->cmd_size = sizeof(struct nvme_rdma_request) + |
| 748 | − SG_CHUNK_SIZE * sizeof(struct scatterlist); | |
| 748 | + NVME_INLINE_SG_CNT * sizeof(struct scatterlist); | |
| 749 | 749 | set->driver_data = ctrl; |
| 750 | 750 | set->nr_hw_queues = nctrl->queue_count - 1; |
| 751 | 751 | set->timeout = NVME_IO_TIMEOUT; |
| @@ -1160,7 +1160,7 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue, · 408 unmodified lines | ||
| 1160 | 1160 | } |
| 1161 | 1161 | |
| 1162 | 1162 | ib_dma_unmap_sg(ibdev, req->sg_table.sgl, req->nents, rq_dma_dir(rq)); |
| 1163 | − sg_free_table_chained(&req->sg_table, SG_CHUNK_SIZE); | |
| 1163 | + sg_free_table_chained(&req->sg_table, NVME_INLINE_SG_CNT); | |
| 1164 | 1164 | } |
| 1165 | 1165 | |
| 1166 | 1166 | static int nvme_rdma_set_sg_null(struct nvme_command *c) |
| @@ -1276,7 +1276,7 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue, · 109 unmodified lines | ||
| 1276 | 1276 | req->sg_table.sgl = req->first_sgl; |
| 1277 | 1277 | ret = sg_alloc_table_chained(&req->sg_table, |
| 1278 | 1278 | blk_rq_nr_phys_segments(rq), req->sg_table.sgl, |
| 1279 | − SG_CHUNK_SIZE); | |
| 1279 | + NVME_INLINE_SG_CNT); | |
| 1280 | 1280 | if (ret) |
| 1281 | 1281 | return -ENOMEM; |
| 1282 | 1282 | |
| @@ -1314,7 +1314,7 @@ out: · 31 unmodified lines | ||
| 1314 | 1314 | out_unmap_sg: |
| 1315 | 1315 | ib_dma_unmap_sg(ibdev, req->sg_table.sgl, req->nents, rq_dma_dir(rq)); |
| 1316 | 1316 | out_free_table: |
| 1317 | − sg_free_table_chained(&req->sg_table, SG_CHUNK_SIZE); | |
| 1317 | + sg_free_table_chained(&req->sg_table, NVME_INLINE_SG_CNT); | |
| 1318 | 1318 | return ret; |
| 1319 | 1319 | } |
| 1320 | 1320 | |
| @@ -850,6 +850,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport) · 849 unmodified lines | ||
| 850 | 850 | #define FCLOOP_DMABOUND_4G 0xFFFFFFFF |
| 851 | 851 | |
| 852 | 852 | static struct nvme_fc_port_template fctemplate = { |
| 853 | + .module = THIS_MODULE, | |
| 853 | 854 | .localport_delete = fcloop_localport_delete, |
| 854 | 855 | .remoteport_delete = fcloop_remoteport_delete, |
| 855 | 856 | .create_queue = fcloop_create_queue, |
| @@ -76,7 +76,7 @@ static void nvme_loop_complete_rq(struct request *req) · 75 unmodified lines | ||
| 76 | 76 | { |
| 77 | 77 | struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(req); |
| 78 | 78 | |
| 79 | − sg_free_table_chained(&iod->sg_table, SG_CHUNK_SIZE); | |
| 79 | + sg_free_table_chained(&iod->sg_table, NVME_INLINE_SG_CNT); | |
| 80 | 80 | nvme_complete_rq(req); |
| 81 | 81 | } |
| 82 | 82 | |
| @@ -156,7 +156,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx, · 73 unmodified lines | ||
| 156 | 156 | iod->sg_table.sgl = iod->first_sgl; |
| 157 | 157 | if (sg_alloc_table_chained(&iod->sg_table, |
| 158 | 158 | blk_rq_nr_phys_segments(req), |
| 159 | − iod->sg_table.sgl, SG_CHUNK_SIZE)) { | |
| 159 | + iod->sg_table.sgl, NVME_INLINE_SG_CNT)) { | |
| 160 | 160 | nvme_cleanup_cmd(req); |
| 161 | 161 | return BLK_STS_RESOURCE; |
| 162 | 162 | } |
| @@ -342,7 +342,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl) · 179 unmodified lines | ||
| 342 | 342 | ctrl->admin_tag_set.reserved_tags = 2; /* connect + keep-alive */ |
| 343 | 343 | ctrl->admin_tag_set.numa_node = NUMA_NO_NODE; |
| 344 | 344 | ctrl->admin_tag_set.cmd_size = sizeof(struct nvme_loop_iod) + |
| 345 | − SG_CHUNK_SIZE * sizeof(struct scatterlist); | |
| 345 | + NVME_INLINE_SG_CNT * sizeof(struct scatterlist); | |
| 346 | 346 | ctrl->admin_tag_set.driver_data = ctrl; |
| 347 | 347 | ctrl->admin_tag_set.nr_hw_queues = 1; |
| 348 | 348 | ctrl->admin_tag_set.timeout = ADMIN_TIMEOUT; |
| @@ -516,7 +516,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl) · 167 unmodified lines | ||
| 516 | 516 | ctrl->tag_set.numa_node = NUMA_NO_NODE; |
| 517 | 517 | ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; |
| 518 | 518 | ctrl->tag_set.cmd_size = sizeof(struct nvme_loop_iod) + |
| 519 | − SG_CHUNK_SIZE * sizeof(struct scatterlist); | |
| 519 | + NVME_INLINE_SG_CNT * sizeof(struct scatterlist); | |
| 520 | 520 | ctrl->tag_set.driver_data = ctrl; |
| 521 | 521 | ctrl->tag_set.nr_hw_queues = ctrl->ctrl.queue_count - 1; |
| 522 | 522 | ctrl->tag_set.timeout = NVME_IO_TIMEOUT; |
| @@ -1976,6 +1976,8 @@ out_unlock: · 1975 unmodified lines | ||
| 1976 | 1976 | |
| 1977 | 1977 | /* Declare and initialization an instance of the FC NVME template. */ |
| 1978 | 1978 | static struct nvme_fc_port_template lpfc_nvme_template = { |
| 1979 | + .module = THIS_MODULE, | |
| 1980 | + | |
| 1979 | 1981 | /* initiator-based functions */ |
| 1980 | 1982 | .localport_delete = lpfc_nvme_localport_delete, |
| 1981 | 1983 | .remoteport_delete = lpfc_nvme_remoteport_delete, |
| @@ -610,6 +610,7 @@ static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport) · 609 unmodified lines | ||
| 610 | 610 | } |
| 611 | 611 | |
| 612 | 612 | static struct nvme_fc_port_template qla_nvme_fc_transport = { |
| 613 | + .module = THIS_MODULE, | |
| 613 | 614 | .localport_delete = qla_nvme_localport_delete, |
| 614 | 615 | .remoteport_delete = qla_nvme_remoteport_delete, |
| 615 | 616 | .create_queue = qla_nvme_alloc_queue, |
| @@ -270,6 +270,8 @@ struct nvme_fc_remote_port { · 269 unmodified lines | ||
| 270 | 270 | * |
| 271 | 271 | * Host/Initiator Transport Entrypoints/Parameters: |
| 272 | 272 | * |
| 273 | + * @module: The LLDD module using the interface | |
| 274 | + * | |
| 273 | 275 | * @localport_delete: The LLDD initiates deletion of a localport via |
| 274 | 276 | * nvme_fc_deregister_localport(). However, the teardown is |
| 275 | 277 | * asynchronous. This routine is called upon the completion of the |
| @@ -383,6 +385,8 @@ struct nvme_fc_remote_port { · 107 unmodified lines | ||
| 383 | 385 | * Value is Mandatory. Allowed to be zero. |
| 384 | 386 | */ |
| 385 | 387 | struct nvme_fc_port_template { |
| 388 | + struct module *module; | |
| 389 | + | |
| 386 | 390 | /* initiator-based functions */ |
| 387 | 391 | void (*localport_delete)(struct nvme_fc_local_port *); |
| 388 | 392 | void (*remoteport_delete)(struct nvme_fc_remote_port *); |