mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
nvme fixes for Linux 6.16
- reset delayed remove_work after reconnect (Keith Busch) - fix atomic write size validation (Christoph Hellwig) -----BEGIN PGP SIGNATURE----- iQI/BAABCgApFiEEgdbnc3r/njty3Iq9D55TZVIEUYMFAmhdKXILHGhjaEBsc3Qu ZGUACgkQD55TZVIEUYOh2A/8CQabNBYW7bOAv7e/6Dx/mb+Rwu65DTyL1pztIsmK Apd8eo987J3GPVh2MI9FRQ9Z75zPnKUGTX2LFMVMqlk3X8AgAR24n+tAQSfciAUM fReqG6RTSkNGRMFbWNsNv6ZTx7Ihw2Q3+yI9BOmmLckn+EG9XEhviW6SvOj2zPfX bFh6z0QnyOUXkaT8h75PaV+9vIfJG85AvQsjIOoV9WToZRd1QHL9bs278gc7ZM7+ EeCHY+zZcnXtmdv3O8u93rRSzmDXIDJOD2v3WPkHqoi2cD6F502+qcxX53vSLuWC Wpl0Wqmrnr9UtrUoxzhc1NUei+u3qdKOBtVgI34br3+W4s7PUx9qZ+3Ai6FjfY4b bhllhdEV6RND0k79Zu45hZGHsbUISyWDemgoJoAPD7qtUjOfxDXT0+fBOgobqcWE /rnJ3GQpKG1H18KsgU7VWBcZa4T+OCqQYQCUKeDvRUzsHu6y7hCb5xDAbwP2kME1 ilbstckgu2RSBW4iGNZiSWk4oMruGF+t51E8iMvKumV5UMHmzAZP67mPbzBehPTM Zt6l0j8KfKZJ3ibteMHOkI8JSVnq2I35Rt1mrxsB4YTGsUwIS0sceTTAbsJ85C2Y dqcwb3jQa99aIlMnjsnAsFgqsr/rLqAHr79nGfHXrGPqlMrQBauNVJT0fkCSoJr0 y9Q= =WezC -----END PGP SIGNATURE----- Merge tag 'nvme-6.16-2025-06-26' of git://git.infradead.org/nvme into block-6.16 Pull NVMe fixes from Christoph: " - reset delayed remove_work after reconnect (Keith Busch) - fix atomic write size validation (Christoph Hellwig)" * tag 'nvme-6.16-2025-06-26' of git://git.infradead.org/nvme: nvme: fix atomic write size validation nvme: refactor the atomic write unit detection nvme: reset delayed remove_work after reconnect
This commit is contained in:
commit
5990b776fb
|
|
@ -2015,21 +2015,41 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl,
|
|||
}
|
||||
|
||||
|
||||
static void nvme_update_atomic_write_disk_info(struct nvme_ns *ns,
|
||||
struct nvme_id_ns *id, struct queue_limits *lim,
|
||||
u32 bs, u32 atomic_bs)
|
||||
static u32 nvme_configure_atomic_write(struct nvme_ns *ns,
|
||||
struct nvme_id_ns *id, struct queue_limits *lim, u32 bs)
|
||||
{
|
||||
unsigned int boundary = 0;
|
||||
u32 atomic_bs, boundary = 0;
|
||||
|
||||
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) {
|
||||
if (le16_to_cpu(id->nabspf))
|
||||
/*
|
||||
* We do not support an offset for the atomic boundaries.
|
||||
*/
|
||||
if (id->nabo)
|
||||
return bs;
|
||||
|
||||
if ((id->nsfeat & NVME_NS_FEAT_ATOMICS) && id->nawupf) {
|
||||
/*
|
||||
* Use the per-namespace atomic write unit when available.
|
||||
*/
|
||||
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
|
||||
if (id->nabspf)
|
||||
boundary = (le16_to_cpu(id->nabspf) + 1) * bs;
|
||||
} else {
|
||||
/*
|
||||
* Use the controller wide atomic write unit. This sucks
|
||||
* because the limit is defined in terms of logical blocks while
|
||||
* namespaces can have different formats, and because there is
|
||||
* no clear language in the specification prohibiting different
|
||||
* values for different controllers in the subsystem.
|
||||
*/
|
||||
atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
|
||||
}
|
||||
|
||||
lim->atomic_write_hw_max = atomic_bs;
|
||||
lim->atomic_write_hw_boundary = boundary;
|
||||
lim->atomic_write_hw_unit_min = bs;
|
||||
lim->atomic_write_hw_unit_max = rounddown_pow_of_two(atomic_bs);
|
||||
lim->features |= BLK_FEAT_ATOMIC_WRITES;
|
||||
return atomic_bs;
|
||||
}
|
||||
|
||||
static u32 nvme_max_drv_segments(struct nvme_ctrl *ctrl)
|
||||
|
|
@ -2067,34 +2087,8 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
|
|||
valid = false;
|
||||
}
|
||||
|
||||
atomic_bs = phys_bs = bs;
|
||||
if (id->nabo == 0) {
|
||||
/*
|
||||
* Bit 1 indicates whether NAWUPF is defined for this namespace
|
||||
* and whether it should be used instead of AWUPF. If NAWUPF ==
|
||||
* 0 then AWUPF must be used instead.
|
||||
*/
|
||||
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf)
|
||||
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
|
||||
else
|
||||
atomic_bs = (1 + ns->ctrl->awupf) * bs;
|
||||
|
||||
/*
|
||||
* Set subsystem atomic bs.
|
||||
*/
|
||||
if (ns->ctrl->subsys->atomic_bs) {
|
||||
if (atomic_bs != ns->ctrl->subsys->atomic_bs) {
|
||||
dev_err_ratelimited(ns->ctrl->device,
|
||||
"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n",
|
||||
ns->disk ? ns->disk->disk_name : "?",
|
||||
ns->ctrl->subsys->atomic_bs,
|
||||
atomic_bs);
|
||||
}
|
||||
} else
|
||||
ns->ctrl->subsys->atomic_bs = atomic_bs;
|
||||
|
||||
nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs);
|
||||
}
|
||||
phys_bs = bs;
|
||||
atomic_bs = nvme_configure_atomic_write(ns, id, lim, bs);
|
||||
|
||||
if (id->nsfeat & NVME_NS_FEAT_IO_OPT) {
|
||||
/* NPWG = Namespace Preferred Write Granularity */
|
||||
|
|
@ -2382,16 +2376,6 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
|
|||
if (!nvme_update_disk_info(ns, id, &lim))
|
||||
capacity = 0;
|
||||
|
||||
/*
|
||||
* Validate the max atomic write size fits within the subsystem's
|
||||
* atomic write capabilities.
|
||||
*/
|
||||
if (lim.atomic_write_hw_max > ns->ctrl->subsys->atomic_bs) {
|
||||
blk_mq_unfreeze_queue(ns->disk->queue, memflags);
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nvme_config_discard(ns, &lim);
|
||||
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
|
||||
ns->head->ids.csi == NVME_CSI_ZNS)
|
||||
|
|
@ -3215,6 +3199,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
|
|||
memcpy(subsys->model, id->mn, sizeof(subsys->model));
|
||||
subsys->vendor_id = le16_to_cpu(id->vid);
|
||||
subsys->cmic = id->cmic;
|
||||
subsys->awupf = le16_to_cpu(id->awupf);
|
||||
|
||||
/* Versions prior to 1.4 don't necessarily report a valid type */
|
||||
if (id->cntrltype == NVME_CTRL_DISC ||
|
||||
|
|
@ -3552,6 +3537,15 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
|
|||
if (ret)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(id->awupf) != ctrl->subsys->awupf) {
|
||||
dev_err_ratelimited(ctrl->device,
|
||||
"inconsistent AWUPF, controller not added (%u/%u).\n",
|
||||
le16_to_cpu(id->awupf), ctrl->subsys->awupf);
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
memcpy(ctrl->subsys->firmware_rev, id->fr,
|
||||
sizeof(ctrl->subsys->firmware_rev));
|
||||
|
||||
|
|
@ -3647,7 +3641,6 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
|
|||
dev_pm_qos_expose_latency_tolerance(ctrl->device);
|
||||
else if (!ctrl->apst_enabled && prev_apst_enabled)
|
||||
dev_pm_qos_hide_latency_tolerance(ctrl->device);
|
||||
ctrl->awupf = le16_to_cpu(id->awupf);
|
||||
out_free:
|
||||
kfree(id);
|
||||
return ret;
|
||||
|
|
@ -4036,6 +4029,10 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
|
|||
list_add_tail_rcu(&ns->siblings, &head->list);
|
||||
ns->head = head;
|
||||
mutex_unlock(&ctrl->subsys->lock);
|
||||
|
||||
#ifdef CONFIG_NVME_MULTIPATH
|
||||
cancel_delayed_work(&head->remove_work);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
out_put_ns_head:
|
||||
|
|
|
|||
|
|
@ -1311,7 +1311,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
|
|||
*/
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
goto out;
|
||||
queue_delayed_work(nvme_wq, &head->remove_work,
|
||||
mod_delayed_work(nvme_wq, &head->remove_work,
|
||||
head->delayed_removal_secs * HZ);
|
||||
} else {
|
||||
list_del_init(&head->entry);
|
||||
|
|
|
|||
|
|
@ -410,7 +410,6 @@ struct nvme_ctrl {
|
|||
|
||||
enum nvme_ctrl_type cntrltype;
|
||||
enum nvme_dctype dctype;
|
||||
u16 awupf; /* 0's based value. */
|
||||
};
|
||||
|
||||
static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
|
||||
|
|
@ -443,11 +442,11 @@ struct nvme_subsystem {
|
|||
u8 cmic;
|
||||
enum nvme_subsys_type subtype;
|
||||
u16 vendor_id;
|
||||
u16 awupf; /* 0's based value. */
|
||||
struct ida ns_ida;
|
||||
#ifdef CONFIG_NVME_MULTIPATH
|
||||
enum nvme_iopolicy iopolicy;
|
||||
#endif
|
||||
u32 atomic_bs;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user