From 87b3975e36ceb2f3ba8233a26f43bd911e5a9ae6 Mon Sep 17 00:00:00 2001 From: Chuck Tuffli Date: Thu, 13 Dec 2018 13:25:37 +0000 Subject: [PATCH] nda(4) fix check for Dataset Management support In the nda(4) driver, only set DISKFLAG_CANDELETE (a.k.a. can support BIO_DELETE) if the drive supports Dataset Management. There are reports that without this check, VMWare Workstation does not work reliably. Fix is to check the ONCS field in the NVMe Controller Data structure for support. This check previously existed but did not survive the big-endian changes. Reported by: yuripv@yuripv.net Reviewed by: imp, mav, jimharris Approved by: imp (mentor) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D18493 --- sys/cam/nvme/nvme_da.c | 2 +- sys/dev/nvme/nvme.h | 7 +++++++ sys/dev/nvme/nvme_ns.c | 6 +----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c index fbb6c4abc661..9e2f26bec07c 100644 --- a/sys/cam/nvme/nvme_da.c +++ b/sys/cam/nvme/nvme_da.c @@ -798,7 +798,7 @@ ndaregister(struct cam_periph *periph, void *arg) disk->d_mediasize = (off_t)(disk->d_sectorsize * nsd->nsze); disk->d_delmaxsize = disk->d_mediasize; disk->d_flags = DISKFLAG_DIRECT_COMPLETION; -// if (cd->oncs.dsm) // XXX broken? + if (nvme_ctrlr_has_dataset_mgmt(cd)) disk->d_flags |= DISKFLAG_CANDELETE; vwc_present = (cd->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) & NVME_CTRLR_DATA_VWC_PRESENT_MASK; diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h index 747767ce9852..845ba75bb9dd 100644 --- a/sys/dev/nvme/nvme.h +++ b/sys/dev/nvme/nvme.h @@ -1259,6 +1259,13 @@ void nvme_unregister_consumer(struct nvme_consumer *consumer); device_t nvme_ctrlr_get_device(struct nvme_controller *ctrlr); const struct nvme_controller_data * nvme_ctrlr_get_data(struct nvme_controller *ctrlr); +static inline bool +nvme_ctrlr_has_dataset_mgmt(const struct nvme_controller_data *cd) +{ + /* Assumes cd was byte swapped by nvme_controller_data_swapbytes() */ + return ((cd->oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) & + NVME_CTRLR_DATA_ONCS_DSM_MASK); +} /* Namespace helper functions */ uint32_t nvme_ns_get_max_io_xfer_size(struct nvme_namespace *ns); diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c index d701b473b00c..5aff90adafc1 100644 --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -498,8 +498,6 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, struct nvme_completion_poll_status status; int res; int unit; - uint16_t oncs; - uint8_t dsm; uint8_t flbas_fmt; uint8_t vwc_present; @@ -569,9 +567,7 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, return (ENXIO); } - oncs = ctrlr->cdata.oncs; - dsm = (oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) & NVME_CTRLR_DATA_ONCS_DSM_MASK; - if (dsm) + if (nvme_ctrlr_has_dataset_mgmt(&ctrlr->cdata)) ns->flags |= NVME_NS_DEALLOCATE_SUPPORTED; vwc_present = (ctrlr->cdata.vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) &