Skip to content

Commit 81adb86

Browse files
bvanasscheChristoph Hellwig
authored andcommitted
nvme: set physical block size and optimal I/O size
>From the NVMe 1.4 spec: NSFEAT bit 4 if set to 1: indicates that the fields NPWG, NPWA, NPDG, NPDA, and NOWS are defined for this namespace and should be used by the host for I/O optimization; [ ... ] Namespace Preferred Write Granularity (NPWG): This field indicates the smallest recommended write granularity in logical blocks for this namespace. This is a 0's based value. The size indicated should be less than or equal to Maximum Data Transfer Size (MDTS) that is specified in units of minimum memory page size. The value of this field may change if the namespace is reformatted. The size should be a multiple of Namespace Preferred Write Alignment (NPWA). Refer to section 8.25 for how this field is utilized to improve performance and endurance. [ ... ] Each Write, Write Uncorrectable, or Write Zeroes commands should address a multiple of Namespace Preferred Write Granularity (NPWG) (refer to Figure 245) and Stream Write Size (SWS) (refer to Figure 515) logical blocks (as expressed in the NLB field), and the SLBA field of the command should be aligned to Namespace Preferred Write Alignment (NPWA) (refer to Figure 245) for best performance. Signed-off-by: Bart Van Assche <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 6605bdd commit 81adb86

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

drivers/nvme/host/core.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,6 +1626,7 @@ static void nvme_update_disk_info(struct gendisk *disk,
16261626
{
16271627
sector_t capacity = le64_to_cpu(id->nsze) << (ns->lba_shift - 9);
16281628
unsigned short bs = 1 << ns->lba_shift;
1629+
u32 atomic_bs, phys_bs, io_opt;
16291630

16301631
if (ns->lba_shift > PAGE_SHIFT) {
16311632
/* unsupported block size, set capacity to 0 later */
@@ -1634,9 +1635,37 @@ static void nvme_update_disk_info(struct gendisk *disk,
16341635
blk_mq_freeze_queue(disk->queue);
16351636
blk_integrity_unregister(disk);
16361637

1638+
if (id->nabo == 0) {
1639+
/*
1640+
* Bit 1 indicates whether NAWUPF is defined for this namespace
1641+
* and whether it should be used instead of AWUPF. If NAWUPF ==
1642+
* 0 then AWUPF must be used instead.
1643+
*/
1644+
if (id->nsfeat & (1 << 1) && id->nawupf)
1645+
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
1646+
else
1647+
atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
1648+
} else {
1649+
atomic_bs = bs;
1650+
}
1651+
phys_bs = bs;
1652+
io_opt = bs;
1653+
if (id->nsfeat & (1 << 4)) {
1654+
/* NPWG = Namespace Preferred Write Granularity */
1655+
phys_bs *= 1 + le16_to_cpu(id->npwg);
1656+
/* NOWS = Namespace Optimal Write Size */
1657+
io_opt *= 1 + le16_to_cpu(id->nows);
1658+
}
1659+
16371660
blk_queue_logical_block_size(disk->queue, bs);
1638-
blk_queue_physical_block_size(disk->queue, bs);
1639-
blk_queue_io_min(disk->queue, bs);
1661+
/*
1662+
* Linux filesystems assume writing a single physical block is
1663+
* an atomic operation. Hence limit the physical block size to the
1664+
* value of the Atomic Write Unit Power Fail parameter.
1665+
*/
1666+
blk_queue_physical_block_size(disk->queue, min(phys_bs, atomic_bs));
1667+
blk_queue_io_min(disk->queue, phys_bs);
1668+
blk_queue_io_opt(disk->queue, io_opt);
16401669

16411670
if (ns->ms && !ns->ext &&
16421671
(ns->ctrl->ops->flags & NVME_F_METADATA_SUPPORTED))
@@ -2433,6 +2462,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
24332462
memcpy(subsys->firmware_rev, id->fr, sizeof(subsys->firmware_rev));
24342463
subsys->vendor_id = le16_to_cpu(id->vid);
24352464
subsys->cmic = id->cmic;
2465+
subsys->awupf = le16_to_cpu(id->awupf);
24362466
#ifdef CONFIG_NVME_MULTIPATH
24372467
subsys->iopolicy = NVME_IOPOLICY_NUMA;
24382468
#endif

drivers/nvme/host/nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ struct nvme_subsystem {
283283
char firmware_rev[8];
284284
u8 cmic;
285285
u16 vendor_id;
286+
u16 awupf; /* 0's based awupf value. */
286287
struct ida ns_ida;
287288
#ifdef CONFIG_NVME_MULTIPATH
288289
enum nvme_iopolicy iopolicy;

0 commit comments

Comments
 (0)