I recently got a Raspberry Pi 3 Model B Plus (Rev 1.3). After
installing current the first thing during boot which I get is:
...
starting network
reordering libraries: done.
starting early daemons: syslogd pflogd ntpd.
starting RPC daemons:.
savecore: no core dump
bcmsdhost0: transfer timeout!
Bus error
checking quotas:Bus error
done.
...
The BCM2835 SD controller is always dying just after savecore(8) has
been executed. My disklabel:
# /dev/rsd0c:
type: SCSI
disk: SCSI disk
label: SD/MMC SD64G
duid: 6f88ece62f92fcb2
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 7764
total sectors: 124735488
boundstart: 65536
boundend: 124735488
drivedata: 0
16 partitions:
# size offset fstype [fsize bsize cpg]
a: 104871040 65536 4.2BSD 2048 16384 12960 # /
b: 19798912 104936576 swap # none
c: 124735488 0 unused
i: 32768 32768 MSDOS
At the end when savecore(8) is reading the swap partition, the last read
request has always triggered the SD controller timeout:
DEBUG: sdhsts=0x80, nblks=8, datalen=4096, arg=0x76f4ff8
0x76f4ff8 = 124735480 + 8 = 124735488
So we overwrite the disk offset by 1 block, which in this case made the
SD controller hang.
Some debugging hours later Theo has finally identified that sdmmc_scsi.c
is having an off-by-one bug during the offset out-of-bounds check.
Following patch fixes that, and makes my Raspberry boot up happily.
OK?
Index: sys/dev/sdmmc/sdmmc_scsi.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_scsi.c,v
retrieving revision 1.59
diff -u -p -u -p -r1.59 sdmmc_scsi.c
--- sys/dev/sdmmc/sdmmc_scsi.c 15 Oct 2020 13:22:13 -0000 1.59
+++ sys/dev/sdmmc/sdmmc_scsi.c 23 Mar 2021 07:32:52 -0000
@@ -365,9 +365,8 @@ sdmmc_scsi_cmd(struct scsi_xfer *xs)
/* A read or write operation. */
sdmmc_scsi_decode_rw(xs, &blockno, &blockcnt);
- if (blockno >= tgt->card->csd.capacity ||
- blockno + blockcnt > tgt->card->csd.capacity) {
- DPRINTF(("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
+ if (blockno + blockcnt >= tgt->card->csd.capacity) {
+ DPRINTF(("%s: out of bounds %u+%u >= %u\n", DEVNAME(sc),
blockno, blockcnt, tgt->card->csd.capacity));
xs->error = XS_DRIVER_STUFFUP;
scsi_done(xs);