From 5074d457e99a2678a1b81448d21db3378eb7a4bd Mon Sep 17 00:00:00 2001 From: Andrew Doran Date: Fri, 19 Jul 2024 11:26:31 -0700 Subject: [PATCH] sleep briefly while flashing Summary: Go idle periodically when flashing the image, to allow other work on the system to happen, for example SPI I/O. For a 32MB flash image, this would result in an extra 8s of idle time during wipe plus 8s during flashing. For S434121. Test Plan: ``` 0 ~/local/openbmc/tools/flashy $ ./build.sh && ./build_dev.sh && go test ./... ? github.com/facebook/openbmc/tools/flashy/flash_procedure [no test files] ? github.com/facebook/openbmc/tools/flashy/lib/logger [no test files] ? github.com/facebook/openbmc/tools/flashy/tests [no test files] ? github.com/facebook/openbmc/tools/flashy/utilities [no test files] ok github.com/facebook/openbmc/tools/flashy 2.024s ok github.com/facebook/openbmc/tools/flashy/checks_and_remediations/bletchley (cached) ok github.com/facebook/openbmc/tools/flashy/checks_and_remediations/common (cached) ok github.com/facebook/openbmc/tools/flashy/checks_and_remediations/galaxy100 (cached) ok github.com/facebook/openbmc/tools/flashy/checks_and_remediations/grandteton (cached) ok github.com/facebook/openbmc/tools/flashy/checks_and_remediations/wedge100 (cached) ok github.com/facebook/openbmc/tools/flashy/checks_and_remediations/yamp (cached) ok github.com/facebook/openbmc/tools/flashy/install 0.007s ok github.com/facebook/openbmc/tools/flashy/lib/fileutils (cached) ok github.com/facebook/openbmc/tools/flashy/lib/flash 0.007s ok github.com/facebook/openbmc/tools/flashy/lib/flash/flashcp 0.508s ok github.com/facebook/openbmc/tools/flashy/lib/flash/flashutils (cached) ok github.com/facebook/openbmc/tools/flashy/lib/flash/flashutils/devices (cached) ok github.com/facebook/openbmc/tools/flashy/lib/step (cached) ok github.com/facebook/openbmc/tools/flashy/lib/utils (cached) ok github.com/facebook/openbmc/tools/flashy/lib/validate (cached) ok github.com/facebook/openbmc/tools/flashy/lib/validate/image (cached) ok github.com/facebook/openbmc/tools/flashy/lib/validate/partition (cached) 0 ~/local/openbmc/tools/flashy $ ``` Build ephemeral fbpkg and flash a wedge100 using it: ``` Host Workflow ID Progress Status Result ---------------------------------- ------------------------------------ ---------- ----------------------- ---------------------- fboss8382003-oob.snc1.facebook.com b4600065-e674-4696-9378-5c313ae45819 finished WorkflowStatus.FINISHED FinishStatus.SUCCEEDED ``` -> https://fburl.com/scuba/openbmc_upgrades/yksvon8b Reviewed By: kawmarco Differential Revision: D59927810 fbshipit-source-id: 7db5bb534575d360816a2ec27bea361936fe16dd --- tools/flashy/lib/flash/flashcp/flashcp.go | 22 ++++++++++++++++++- .../flashy/lib/flash/flashcp/flashcp_test.go | 18 +++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/tools/flashy/lib/flash/flashcp/flashcp.go b/tools/flashy/lib/flash/flashcp/flashcp.go index fae738500a5d..111fd95744c7 100644 --- a/tools/flashy/lib/flash/flashcp/flashcp.go +++ b/tools/flashy/lib/flash/flashcp/flashcp.go @@ -41,6 +41,7 @@ import ( "os" "regexp" "syscall" + "time" "unsafe" "github.com/facebook/openbmc/tools/flashy/lib/fileutils" @@ -83,6 +84,7 @@ type mtd_info_user struct { const sizeof_mtd_info_user = 32 const sizeof_erase_user_info = 8 +const chunkSize = uint32(1048576) // linux/include/uapi/mtd/mtd-abi.h var MEMGETINFO = ioctl.IOR('M', 1, sizeof_mtd_info_user) @@ -254,6 +256,8 @@ var eraseFlashDevice = func( imFile imageFile, roOffset uint32, ) error { + sleepTodo := int32(chunkSize) + log.Printf("Erasing flash device '%v'...", deviceFile.Name()) if m.erasesize == 0 { @@ -293,6 +297,18 @@ var eraseFlashDevice = func( log.Print(errMsg) return errors.Errorf("%v", errMsg) } + + // For every chunkSize bytes of work done, sleep for 1/4s to + // allow for other work on the system (especially I/O to the + // SPI) to complete. + // + // In practice erasesize will be smaller than chunkSize but + // in any case this will still trigger every so often. + sleepTodo = sleepTodo - int32(m.erasesize); + if sleepTodo <= 0 { + sleepTodo = int32(chunkSize); + utils.Sleep(time.Millisecond * 250); + } } log.Printf("Finished erasing flash device '%v'", deviceFile.Name()) @@ -306,7 +322,6 @@ var flashImage = func( imFile imageFile, roOffset uint32, ) error { - const chunkSize = uint32(1048576) fileSize := uint32(len(imFile.data)) log.Printf("Flashing image '%v' on to flash device '%v'", imFile.name, deviceFile.Name()) @@ -336,6 +351,11 @@ var flashImage = func( imFile.name, deviceFile.Name(), n, err, ) } + + // For every chunkSize bytes of work done, sleep for 1/4s to + // allow for other work on the system (especially I/O to the + // SPI) to complete. + utils.Sleep(time.Millisecond * 250); } log.Printf("Finished flashing image '%v' on to flash device '%v'", diff --git a/tools/flashy/lib/flash/flashcp/flashcp_test.go b/tools/flashy/lib/flash/flashcp/flashcp_test.go index 340a7058e45a..a3355a2ba3ef 100644 --- a/tools/flashy/lib/flash/flashcp/flashcp_test.go +++ b/tools/flashy/lib/flash/flashcp/flashcp_test.go @@ -23,6 +23,7 @@ import ( "bytes" "math" "testing" + "time" "unsafe" "github.com/facebook/openbmc/tools/flashy/lib/fileutils" @@ -59,6 +60,7 @@ func TestFlashCp(t *testing.T) { runFlashProcessOrig := runFlashProcess closeFileOrig := closeFlashDeviceFile PetWatchdogOrig := utils.PetWatchdog + sleepOrig := utils.Sleep defer func() { openFlashDeviceFile = openFileOrig getMtdInfoUser = getMtdInfoUserOrig @@ -67,6 +69,7 @@ func TestFlashCp(t *testing.T) { runFlashProcess = runFlashProcessOrig closeFlashDeviceFile = closeFileOrig utils.PetWatchdog = PetWatchdogOrig + utils.Sleep = sleepOrig }() cases := []struct { @@ -168,6 +171,7 @@ func TestFlashCp(t *testing.T) { } utils.PetWatchdog = func() { } + utils.Sleep = func(t time.Duration) {} for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -227,6 +231,7 @@ func TestRunFlashProcess(t *testing.T) { flashImageOrig := flashImage verifyFlashOrig := verifyFlash PetWatchdogOrig := utils.PetWatchdog + sleepOrig := utils.Sleep defer func() { openFlashDeviceFile = openFlashDeviceFileOrig closeFlashDeviceFile = closeFlashDeviceFileOrig @@ -235,6 +240,7 @@ func TestRunFlashProcess(t *testing.T) { flashImage = flashImageOrig verifyFlash = verifyFlashOrig utils.PetWatchdog = PetWatchdogOrig + utils.Sleep = sleepOrig }() cases := []struct { @@ -298,6 +304,7 @@ func TestRunFlashProcess(t *testing.T) { } utils.PetWatchdog = func() { } + utils.Sleep = func(t time.Duration) {} for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -441,8 +448,10 @@ func TestHealthCheck(t *testing.T) { func TestEraseFlashDevice(t *testing.T) { IOCTLOrig := IOCTL + sleepOrig := utils.Sleep defer func() { IOCTL = IOCTLOrig + utils.Sleep = sleepOrig }() imData := []byte("foobar") @@ -529,6 +538,7 @@ func TestEraseFlashDevice(t *testing.T) { fileutils.Munmap = func(data []byte) error { return nil } + utils.Sleep = func(t time.Duration) {} for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { @@ -566,8 +576,10 @@ func TestEraseFlashDevice(t *testing.T) { func TestFlashImage(t *testing.T) { pwriteOrig := fileutils.Pwrite + sleepOrig := utils.Sleep defer func() { fileutils.Pwrite = pwriteOrig + utils.Sleep = sleepOrig }() imData := []byte("foobar") @@ -610,6 +622,9 @@ func TestFlashImage(t *testing.T) { want: errors.Errorf("roOffset (100) >= file size (6)"), }, } + + utils.Sleep = func(t time.Duration) {} + for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { fileutils.Pwrite = func(fd int, p []byte, roOffset int64) (n int, err error) { @@ -642,13 +657,16 @@ func TestFlashImage(t *testing.T) { func TestVerifyFlash(t *testing.T) { mmapFileRangeOrig := fileutils.MmapFileRange munmapOrig := fileutils.Munmap + sleepOrig := utils.Sleep defer func() { fileutils.MmapFileRange = mmapFileRangeOrig fileutils.Munmap = munmapOrig + utils.Sleep = sleepOrig }() fileutils.Munmap = func(b []byte) error { return nil } + utils.Sleep = func(t time.Duration) {} imData := []byte("foobar") imFile := imageFile{