svn commit: r366261 - stable/12/sbin/nvmecontrol
David Bright
dab at FreeBSD.org
Tue Sep 29 16:38:57 UTC 2020
Author: dab
Date: Tue Sep 29 16:38:56 2020
New Revision: 366261
URL: https://svnweb.freebsd.org/changeset/base/366261
Log:
MFC r365948:
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
identify-controller response to set the max transfer size.
- 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.
Sponsored by: Dell EMC Isilon
Modified:
stable/12/sbin/nvmecontrol/firmware.c
stable/12/sbin/nvmecontrol/identify_ext.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sbin/nvmecontrol/firmware.c
==============================================================================
--- stable/12/sbin/nvmecontrol/firmware.c Tue Sep 29 16:29:50 2020 (r366260)
+++ stable/12/sbin/nvmecontrol/firmware.c Tue Sep 29 16:38:56 2020 (r366261)
@@ -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: stable/12/sbin/nvmecontrol/identify_ext.c
==============================================================================
--- stable/12/sbin/nvmecontrol/identify_ext.c Tue Sep 29 16:29:50 2020 (r366260)
+++ stable/12/sbin/nvmecontrol/identify_ext.c Tue Sep 29 16:38:56 2020 (r366261)
@@ -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