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