svn commit: r365948 - head/sbin/nvmecontrol
David Bright
dab at FreeBSD.org
Mon Sep 21 15:45:50 UTC 2020
Author: dab
Date: Mon Sep 21 15:45:49 2020
New Revision: 365948
URL: https://svnweb.freebsd.org/changeset/base/365948
Log:
Honor the FWUG value of some drives in nvmecontrol
nvmecontrol tries to upload firmware in chunks as large as it thinks
the device permits. It fails to take into account the FWUG value used
by some drives to advertise the size and alignment limits for firmware
chunks.
- Use the firwmare update granularity value from the
- If the granularity is not reported or not restricted, fall back to
the previously existing logic that calculates the max transfer
size based on MDTS.
- Add firmware update granularity to the identify-controller output.
Reviewed by: imp (previous version), chuck
Obtained from: Dell EMC Isilon
MFC after: 1 week
Sponsored by: Dell EMC Isilon
Differential Revision: https://reviews.freebsd.org/D26390
Modified:
head/sbin/nvmecontrol/firmware.c
head/sbin/nvmecontrol/identify_ext.c
Modified: head/sbin/nvmecontrol/firmware.c
==============================================================================
--- head/sbin/nvmecontrol/firmware.c Mon Sep 21 15:44:23 2020 (r365947)
+++ head/sbin/nvmecontrol/firmware.c Mon Sep 21 15:45:49 2020 (r365948)
@@ -155,21 +155,29 @@ read_image_file(const char *path, void **buf, int32_t
}
static void
-update_firmware(int fd, uint8_t *payload, int32_t payload_size)
+update_firmware(int fd, uint8_t *payload, int32_t payload_size, uint8_t fwug)
{
struct nvme_pt_command pt;
+ uint64_t max_xfer_size;
int32_t off, resid, size;
void *chunk;
off = 0;
resid = payload_size;
- if ((chunk = aligned_alloc(PAGE_SIZE, NVME_MAX_XFER_SIZE)) == NULL)
- errx(1, "unable to malloc %d bytes", NVME_MAX_XFER_SIZE);
+ if (fwug != 0 && fwug != 0xFF)
+ max_xfer_size = ((uint64_t)fwug << 12);
+ else if (ioctl(fd, NVME_GET_MAX_XFER_SIZE, &max_xfer_size) < 0)
+ err(1, "query max transfer size failed");
+ if (max_xfer_size > NVME_MAX_XFER_SIZE)
+ max_xfer_size = NVME_MAX_XFER_SIZE;
+ if ((chunk = aligned_alloc(PAGE_SIZE, max_xfer_size)) == NULL)
+ errx(1, "unable to malloc %zd bytes", (size_t)max_xfer_size);
+
while (resid > 0) {
- size = (resid >= NVME_MAX_XFER_SIZE) ?
- NVME_MAX_XFER_SIZE : resid;
+ size = (resid >= (int32_t)max_xfer_size) ?
+ max_xfer_size : resid;
memcpy(chunk, payload + off, size);
memset(&pt, 0, sizeof(pt));
@@ -333,7 +341,7 @@ firmware(const struct cmd *f, int argc, char *argv[])
}
if (opt.fw_img != NULL) {
- update_firmware(fd, buf, size);
+ update_firmware(fd, buf, size, cdata.fwug);
if (opt.activate)
activate_action = NVME_AA_REPLACE_ACTIVATE;
else
Modified: head/sbin/nvmecontrol/identify_ext.c
==============================================================================
--- head/sbin/nvmecontrol/identify_ext.c Mon Sep 21 15:44:23 2020 (r365947)
+++ head/sbin/nvmecontrol/identify_ext.c Mon Sep 21 15:45:49 2020 (r365948)
@@ -56,6 +56,7 @@ nvme_print_controller(struct nvme_controller_data *cda
uint8_t ns_smart;
uint8_t sqes_max, sqes_min;
uint8_t cqes_max, cqes_min;
+ uint8_t fwug;
oncs = cdata->oncs;
compare = (oncs >> NVME_CTRLR_DATA_ONCS_COMPARE_SHIFT) &
@@ -79,6 +80,7 @@ nvme_print_controller(struct nvme_controller_data *cda
NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
fw_slot1_ro = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) &
NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK;
+ fwug = cdata->fwug;
ns_smart = (cdata->lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) &
NVME_CTRLR_DATA_LPA_NS_SMART_MASK;
@@ -192,6 +194,13 @@ nvme_print_controller(struct nvme_controller_data *cda
uint128_to_str(to128(cdata->untncap.unvmcap),
cbuf, sizeof(cbuf)));
}
+ printf("Firmware Update Granularity: %02x ", fwug);
+ if (fwug == 0)
+ printf("(Not Reported)\n");
+ else if (fwug == 0xFF)
+ printf("(No Granularity)\n");
+ else
+ printf("(%d bytes)\n", ((uint32_t)fwug << 12));
printf("Host Buffer Preferred Size: %llu bytes\n",
(long long unsigned)cdata->hmpre * 4096);
printf("Host Buffer Minimum Size: %llu bytes\n",
More information about the svn-src-all
mailing list