nvme: add virt boundary per ctrl
Subsystems (3)
PATCH 1/3 nvme: add virt boundary per ctrl
Prepare an infrastructure for controllers that can handle arbitrarily sized bios (e.g advanced RDMA and PCI ctrls). Add virt_boundary_mask according to each ctrl constraints.
--- drivers/nvme/host/core.c | 2 +- drivers/nvme/host/fc.c | 1 + drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/pci.c | 1 + drivers/nvme/host/rdma.c | 1 + drivers/nvme/target/loop.c | 1 + 6 files changed, 6 insertions(+), 1 deletions(-)
drivers/nvme/host/core.c +1 -1
@@ -1503,7 +1503,7 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, }if (ctrl->quirks &NVME_QUIRK_STRIPE_SIZE )blk_queue_chunk_sectors (q, ctrl->max_hw_sectors); -blk_queue_virt_boundary (q, ctrl->page_size -1 ); +blk_queue_virt_boundary (q, ctrl->virt_boundary_mask);if (ctrl->vwc &NVME_CTRL_VWC_PRESENT ) vwc = true;blk_queue_write_cache (q, vwc, vwc);
drivers/nvme/host/fc.c +1 -0
@@ -2354,6 +2354,7 @@ enum { segs =min_t (u32,NVME_FC_MAX_SEGMENTS , ctrl->lport->ops->max_sgl_segments); ctrl->ctrl.max_hw_sectors = (segs -1 ) << (PAGE_SHIFT -9 ); + ctrl->ctrl.virt_boundary_mask = ctrl->ctrl.page_size -1 ; ret =nvme_init_identify (&ctrl->ctrl);if (ret)
drivers/nvme/host/nvme.h +1 -0
@@ -167,6 +167,7 @@ struct nvme_ctrl {struct work_struct scan_work;struct work_struct async_event_work;struct delayed_work ka_work; +unsigned long virt_boundary_mask;/* Power saving configuration */ u64 ps_max_latency_us;
drivers/nvme/host/pci.c +1 -0
@@ -2140,6 +2140,7 @@ static void nvme_reset_work(struct work_struct *work)if (result) goto out; + dev->ctrl.virt_boundary_mask = dev->ctrl.page_size -1 ; result =nvme_init_identify (&dev->ctrl);if (result) goto out;
drivers/nvme/host/rdma.c +1 -0
@@ -1584,6 +1584,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl) ctrl->ctrl.max_hw_sectors = (ctrl->max_fr_pages -1 ) << (PAGE_SHIFT -9 ); + ctrl->ctrl.virt_boundary_mask = ctrl->ctrl.page_size -1 ; error =nvme_init_identify (&ctrl->ctrl);if (error)
drivers/nvme/target/loop.c +1 -0
@@ -402,6 +402,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl) ctrl->ctrl.max_hw_sectors = (NVME_LOOP_MAX_SEGMENTS -1 ) << (PAGE_SHIFT -9 ); + ctrl->ctrl.virt_boundary_mask = ctrl->ctrl.page_size -1 ; error =nvme_init_identify (&ctrl->ctrl);if (error)
Signature · 1 line
1.7.1
PATCH 2/3 nvme: introduce max_segments controller attribute
Each ctrl will limit max_segments according to it's hardware restrictions. Implement the restriction for RDMA transport.
--- drivers/nvme/host/core.c | 4 ++-- drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/rdma.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-)
drivers/nvme/host/core.c +2 -2
@@ -1495,8 +1495,8 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,bool vwc = false;if (ctrl->max_hw_sectors) { -u32 max_segments = - (ctrl->max_hw_sectors / (ctrl->page_size >>9 )) +1 ; +u32 max_segments =min_not_zero (ctrl->max_segments, + (ctrl->max_hw_sectors / (ctrl->page_size >>9 )) +1 );blk_queue_max_hw_sectors (q, ctrl->max_hw_sectors);blk_queue_max_segments (q,min_t (u32, max_segments,USHRT_MAX ));
drivers/nvme/host/nvme.h +1 -0
@@ -147,6 +147,7 @@ struct nvme_ctrl {u64 cap;u32 page_size;u32 max_hw_sectors; +u32 max_segments;u16 oncs;u16 vid;u16 oacs;
drivers/nvme/host/rdma.c +1 -0
@@ -1582,6 +1582,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)if (error) goto out_cleanup_queue; + ctrl->ctrl.max_segments = ctrl->max_fr_pages; ctrl->ctrl.max_hw_sectors = (ctrl->max_fr_pages -1 ) << (PAGE_SHIFT -9 ); ctrl->ctrl.virt_boundary_mask = ctrl->ctrl.page_size -1 ;
Signature · 1 line
1.7.1
Sagi Grimberg
maintainerPATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 16 lines
Each ctrl will limit
max_segmentsaccording to it's hardware restrictions. Implement the restriction for RDMA transport.Signed-off-by Max Gurtovoy <maxg at mellanox.com>--- drivers/nvme/host/core.c | 4 ++-- drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/rdma.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-)drivers/nvme/host/core.c +0
-0
drivers/nvme/host/core.c static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, · line 1499
Quoted 7 lines
drivers/nvme/host/core.c +2
-2@@ -1495,8 +1495,8 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,bool vwc = false;if (ctrl->max_hw_sectors) { -u32 max_segments = - (ctrl->max_hw_sectors / (ctrl->page_size >>9 )) +1 ; +u32 max_segments =min_not_zero (ctrl->max_segments, + (ctrl->max_hw_sectors / (ctrl->page_size >>9 )) +1 );
Why is this needed with patches 1,3 applied?
We set the page_size and we set max_hw_sectors accordingly.
PATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 26 lines · Sagi Grimberg
Quoted 16 lines
Each ctrl will limit
max_segmentsaccording to it's hardware restrictions. Implement the restriction for RDMA transport.Signed-off-by Max Gurtovoy <maxg at mellanox.com>--- drivers/nvme/host/core.c | 4 ++-- drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/rdma.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-)drivers/nvme/host/core.c +0
-0drivers/nvme/host/core.c static void nvme_set_queue_limits(struct · line 1499
Quoted 7 lines
drivers/nvme/host/core.c +2
-2@@ -1495,8 +1495,8 @@ static void nvme_set_queue_limits(structnvme_ctrl *ctrl, bool vwc = false;if (ctrl->max_hw_sectors) { -u32 max_segments = - (ctrl->max_hw_sectors / (ctrl->page_size >>9 )) +1 ; +u32 max_segments =min_not_zero (ctrl->max_segments, + (ctrl->max_hw_sectors / (ctrl->page_size >>9 )) +1 );Why is this needed with patches 1,3 applied?
Quoted 1 line
We set the
page_sizeand we setmax_hw_sectorsaccordingly.
We didn't touch the ctrl->page_size. It's always 4k (the target checks it). This may cause max_segments to be bigger than hw limitation (in PPC for example).
Sagi Grimberg
maintainerPATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 8 lines
Quoted 4 lines
Why is this needed with patches 1,3 applied?
We set the
page_sizeand we setmax_hw_sectorsaccordingly.We didn't touch the
ctrl->page_size. It's always 4k (the target checks it). This may causemax_segmentsto be bigger than hw limitation (in PPC for example).
Right, got confused for a second, but why shouldn't we modify the ctrl page_size in rdma? Its not really a controller attribute, but rather the local HCA attribute really.
Or, we could simply fix nvme-core to take PAGE_SIZE if supported by the ctrl and fallback to 4k otherwise.
Christoph Hellwig
maintainerPATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 5 lines · Sagi Grimberg
Quoted 5 lines
Quoted 4 lines
Why is this needed with patches 1,3 applied?
We set the
page_sizeand we setmax_hw_sectorsaccordingly.
Quoted 7 lines
Quoted 3 lines
We didn't touch the
ctrl->page_size. It's always 4k (the target checks it). This may causemax_segmentsto be bigger than hw limitation (in PPC for example).Right, got confused for a second, but why shouldn't we modify the ctrl
page_sizein rdma? Its not really a controller attribute, but rather the local HCA attribute really.
But the controller needs to support it, and NVMe controllers are only required to support a 4k page size, the rest is optional.
Quoted 2 lines
Or, we could simply fix nvme-core to take
PAGE_SIZEif supported by the ctrl and fallback to 4k otherwise.
For PCIe (before fabrics existed) we used to do that, but we changed it for ppc64 in this commit:
c5c9f25b98 ("NVMe: default to 4k device page size")
Sagi Grimberg
maintainerPATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines
Why is this needed with patches 1,3 applied?
We set the
page_sizeand we setmax_hw_sectorsaccordingly.We didn't touch the
ctrl->page_size. It's always 4k (the target checks it). This may causemax_segmentsto be bigger than hw limitation (in PPC for example).
Quoted 6 lines
Quoted 3 lines
Right, got confused for a second, but why shouldn't we modify the ctrl
page_sizein rdma? Its not really a controller attribute, but rather the local HCA attribute really.But the controller needs to support it, and NVMe controllers are only required to support a 4k page size, the rest is optional.
How exacly is the controller required to support the pag_size for fabrics?
It could have implications on mdts, but AFAIR, mdts is reported in units of MPSMIN so I'm not exactly sure how exactly the controller needs to support it.
Quoted 7 lines
Quoted 2 lines
Or, we could simply fix nvme-core to take
PAGE_SIZEif supported by the ctrl and fallback to 4k otherwise.For PCIe (before fabrics existed) we used to do that, but we changed it for ppc64 in this commit:
c5c9f25b98("NVMe: default to 4k device page size")
Yea... I'm wandering if this is specific to NVMe or it can trigger in RDMA as well.
Note that for iSER we always use 4k page vectors, but that was historically done before we had gaps detection in the block layer and we had higher chance to do bounce buffering in iSER.
Christoph Hellwig
maintainerPATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 5 lines · Sagi Grimberg
Quoted 2 lines
But the controller needs to support it, and NVMe controllers are only required to support a 4k page size, the rest is optional.
How exacly is the controller required to support the
pag_sizefor fabrics?
It doesn't matter at all, except as the scaling factor for a few reported values.
Quoted 7 lines
Quoted 4 lines
For PCIe (before fabrics existed) we used to do that, but we changed it for ppc64 in this commit:
c5c9f25b98("NVMe: default to 4k device page size")Yea... I'm wandering if this is specific to NVMe or it can trigger in RDMA as well.
As far as I can tell we could hit it with RDMA under the same circumstances (weird iommu with a smaller page size than the system page size), but for RDMA the nvme controller page size isn't the one that matter, but rather the MR page size.
So for now to be safe it might be a good idea to always use a 4k MR page size..
PATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 3 lines
So for now to be safe it might be a good idea to always use a 4k MR page size..
So should I send a fix only for the MR page size (4k) for now ? Or should we add the infrastructure for virt_boundary and max_segments per ctrl too ?
Christoph Hellwig
maintainerPATCH 2/3 nvme: introduce max_segments controller attribute
Quoted 7 lines · Max Gurtovoy
Quoted 3 lines
So for now to be safe it might be a good idea to always use a 4k MR page size..
So should I send a fix only for the MR page size (4k) for now ? Or should we add the infrastructure for
virt_boundaryandmax_segmentsper ctrl too ?
We'll eventually want both, but for 4.13 fixing the MR page size to 4k should be fine.
PATCH 3/3 nvme-rdma: fix virtual boundary calculation
In reply to Max GurtovoySet the virtual boundary to correspond the mapping restrictions of the HCA. This fixes the mismatch in systems with page size > 4KiB.
--- drivers/nvme/host/rdma.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/nvme/host/rdma.c +1 -1
@@ -1585,7 +1585,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl) ctrl->ctrl.max_segments = ctrl->max_fr_pages; ctrl->ctrl.max_hw_sectors = (ctrl->max_fr_pages -1 ) << (PAGE_SHIFT -9 ); - ctrl->ctrl.virt_boundary_mask = ctrl->ctrl.page_size -1 ; + ctrl->ctrl.virt_boundary_mask =PAGE_SIZE -1 ; error =nvme_init_identify (&ctrl->ctrl);if (error)
Signature · 1 line
1.7.1
PATCH 1/3 nvme: add virt boundary per ctrl
In reply to Max GurtovoyQuoted 5 lines · Max Gurtovoy
Prepare an infrastructure for controllers that can handle arbitrarily sized bios (e.g advanced RDMA and PCI ctrls). Add
virt_boundary_maskaccording to each ctrl constraints.Signed-off-by Max Gurtovoy <maxg at mellanox.com>
Quoted 10 lines
--- drivers/nvme/host/core.c | 2 +- drivers/nvme/host/fc.c | 1 + drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/pci.c | 1 + drivers/nvme/host/rdma.c | 1 + drivers/nvme/target/loop.c | 1 + 6 files changed, 6 insertions(+), 1 deletions(-)
Looks fine to me.