Bug 258994 - iic(4): Panics on Nanopi Neo when using 16-bit device addressing width: panic: Assertion strlen(description) < MAX_W_NAME failed at ... sys/kern/subr_witness.c:1914
Summary: iic(4): Panics on Nanopi Neo when using 16-bit device addressing width: panic...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.2-RELEASE
Hardware: arm Any
: --- Affects Some People
Assignee: Andriy Gapon
URL:
Keywords: crash, needs-qa
Depends on:
Blocks:
 
Reported: 2021-10-07 23:11 UTC by alydiomc
Modified: 2021-12-17 07:34 UTC (History)
5 users (show)

See Also:
koobs: mfc-stable13?
koobs: mfc-stable12?


Attachments
twsi.c driver (21.18 KB, text/plain)
2021-10-12 11:55 UTC, alydiomc
no flags Details
Added some improvements. (7.65 KB, patch)
2021-10-19 07:39 UTC, alydiomc
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description alydiomc 2021-10-07 23:11:02 UTC
On Nanopi NEO (Allwinner H3), accessing I2C EEPROM with 16-bit addressing width panics the OS. This seems working on RPI.

Same issue experienced on:
    FreeBSD 12.2 Release
    FreeBSD 13.0 Release
    FreeBSD 13.0 Stable

root@nanopi-neo:~ # uname -a
FreeBSD nanopi-neo 14.0-CURRENT FreeBSD 14.0-CURRENT #1 main-n249946-824bbb9a408-dirty: Fri Oct  8 05:34:21 PST 2021     root@media.klyren.net:/zdata0/work/obj/zdata0/src-14-CURRENT/arm.armv7/sys/GENERIC  arm

root@nanopi-neo:~ # dmesg |grep ii
iichb0: <Allwinner Integrated I2C Bus Controller> mem 0x1c2ac00-0x1c2afff irq 40 on simplebus0
iicbus0: <OFW I2C bus> on iichb0
miibus0: <MII bus> on awg0
ukphy0: <Generic IEEE 802.3u media interface> PHY 0 on miibus0
ukphy1: <Generic IEEE 802.3u media interface> PHY 1 on miibus0
iic0: <I2C generic I/O> on iicbus0

root@nanopi-neo:~ # i2c -s -f /dev/iic0
57 68

root@nanopi-neo:~ # i2c -a 0x57 -f /dev/iic0 -d r -o 1 -w 16 -c 1 -m tr
panic: Assertion strlen(description) < MAX_W_NAME failed at /zdata0/src-14-CURRENT/sys/kern/subr_witness.c:1914
ðñòóôõö÷øùúûüýþÿtime = 1633646823
KDB: stack backtrace:
db_trace_self() at db_trace_self
         pc = 0xc05b2e24  lr = 0xc007b07c (db_trace_self_wrapper+0x30)
         sp = 0xd89e8928  fp = 0xd89e8a40
db_trace_self_wrapper() at db_trace_self_wrapper+0x30
         pc = 0xc007b07c  lr = 0xc02dddbc (vpanic+0x17c)
         sp = 0xd89e8a48  fp = 0xd89e8a68
         r4 = 0x00000100  r5 = 0x00000000
         r6 = 0xc0708d0c  r7 = 0xc08e8aa8
vpanic() at vpanic+0x17c
         pc = 0xc02dddbc  lr = 0xc02ddb60 (doadump)
         sp = 0xd89e8a70  fp = 0xd89e8a74
         r4 = 0xc10a0878  r5 = 0xc10a0830
         r6 = 0xc08be7bc  r7 = 0xc079bd0e
         r8 = 0x0000019e  r9 = 0x0000019d
        r10 = 0xc0ad95f0
doadump() at doadump
         pc = 0xc02ddb60  lr = 0xc034f3b4 (enroll+0x540)
         sp = 0xd89e8a7c  fp = 0xd89e8aa8
         r4 = 0xc0ad95f0  r5 = 0xd89e8a74
         r6 = 0xc02ddb60 r10 = 0xd89e8a7c
enroll() at enroll+0x540
         pc = 0xc034f3b4  lr = 0xc034f878 (witness_init+0xb0)
         sp = 0xd89e8ab0  fp = 0xd89e8ab8
         r4 = 0xd2caffa0  r5 = 0x00000000
         r6 = 0xd8f2b754  r7 = 0xc00b1074
         r8 = 0xd8cc17c0  r9 = 0xc0889ed0
        r10 = 0xd2e0e040
witness_init() at witness_init+0xb0
         pc = 0xc034f878  lr = 0xc02e7b04 (sx_init_flags+0x88)
         sp = 0xd89e8ac0  fp = 0xd89e8ad0
         r4 = 0xd2caffa0 r10 = 0xd2e0e040
sx_init_flags() at sx_init_flags+0x88
         pc = 0xc02e7b04  lr = 0xc00b10b8 (iicopen+0x44)
         sp = 0xd89e8ad8  fp = 0xd89e8ae0
         r4 = 0xd2caffa0  r5 = 0xd2a4ce00
iicopen() at iicopen+0x44
         pc = 0xc00b10b8  lr = 0xc01d8784 (devfs_open+0x12c)
         sp = 0xd89e8ae8  fp = 0xd89e8b20
         r4 = 0xd2a4ce00  r5 = 0x00000000
devfs_open() at devfs_open+0x12c
         pc = 0xc01d8784  lr = 0xc06a5324 (VOP_OPEN_APV+0x50)
         sp = 0xd89e8b28  fp = 0xd89e8b40
         r4 = 0xd89e8b50  r5 = 0xc08a9fd4
         r6 = 0xc09138c5  r7 = 0x00000003
         r8 = 0xd8f71e00  r9 = 0xd89e8b50
        r10 = 0xd8cc17c0
VOP_OPEN_APV() at VOP_OPEN_APV+0x50
         pc = 0xc06a5324  lr = 0xc03e0dec (vn_open_vnode+0x184)
         sp = 0xd89e8b48  fp = 0xd89e8ba8
         r4 = 0xd8f2b754  r5 = 0x00000000
         r6 = 0xd2e0e040 r10 = 0xd8cc17c0
vn_open_vnode() at vn_open_vnode+0x184
         pc = 0xc03e0dec  lr = 0xc03e0828 (vn_open_cred+0x578)
         sp = 0xd89e8bb0  fp = 0xd89e8cc0
         r4 = 0x00000001  r5 = 0xd89e8cf8
         r6 = 0x00000003  r7 = 0xd89e8d58
         r8 = 0xd89e8dc0  r9 = 0x00000000
        r10 = 0x00000000
vn_open_cred() at vn_open_cred+0x578
         pc = 0xc03e0828  lr = 0xc03e02a8 (vn_open+0x24)
         sp = 0xd89e8cc8  fp = 0xd89e8cd0
         r4 = 0xd8cc17c0  r5 = 0xd89e8cf8
         r6 = 0x00000000  r7 = 0xd89e8cf8
         r8 = 0xffffff9c  r9 = 0x00000012
        r10 = 0xbfbfee4b
vn_open() at vn_open+0x24
         pc = 0xc03e02a8  lr = 0xc03d6f30 (kern_openat+0x258)
         sp = 0xd89e8cd8  fp = 0xd89e8db8
kern_openat() at kern_openat+0x258
         pc = 0xc03d6f30  lr = 0xc03d71b8 (sys_openat+0x2c)
         sp = 0xd89e8dc0  fp = 0xd89e8dc8
         r4 = 0xd8cc17c0  r5 = 0x00000001
         r6 = 0xc08b42bc  r7 = 0x00000000
         r8 = 0x00000000  r9 = 0xd8cc1a68
        r10 = 0xd8cc0530
sys_openat() at sys_openat+0x2c
         pc = 0xc03d71b8  lr = 0xc05d5128 (swi_handler+0x15c)
         sp = 0xd89e8dd0  fp = 0xd89e8e40
swi_handler() at swi_handler+0x15c
         pc = 0xc05d5128  lr = 0xc05b574c (swi_exit)
         sp = 0xd89e8e48  fp = 0xbfbfe780
         r4 = 0x201f8a44  r5 = 0x00044190
         r6 = 0xbfbfec98  r7 = 0x000001f3
         r8 = 0x00000001  r9 = 0x00010b92
        r10 = 0x00000000
swi_exit() at swi_exit
         pc = 0xc05b574c  lr = 0xc05b574c (swi_exit)
         sp = 0xd89e8e48  fp = 0xbfbfe780
KDB: enter: panic
[ thread pid 985 tid 100114 ]
Stopped at      kdb_enter+0x58: ldrb    r15, [r15, r15, ror r15]!
db> ps
  pid  ppid  pgrp   uid  state   wmesg   wchan       cmd
  985   972   985     0  R+      CPU 1               i2c
  972   971   972     0  S+      pause   0xd8cc0928  csh
  971     1   971     0  Ss+     wait    0xd2dacc40  login
  952     1   952     0  Ss      select  0xd2c954a4  sshd
  925     1   925     0  Ss      nanslp  0xc0ac3d8e  cron
  914     1   914   123  Ss      (threaded)          ntpd
100117                   S       select  0xd2ccb224  ntpd
100122                   S       usem    0xd2dc5e80  ntpd
  870     1   870     0  Ss      select  0xd2cb2664  syslogd
  682     1   682     0  Ss      select  0xd2cb2524  devd
  284     1   284     0  Ss      select  0xd2cb2624  wpa_supplicant
   23     0     0     0  DL      mmcsd d 0xd2ccce00  [mmcsd0: mmc/sd card]
   22     0     0     0  DL      -       0xc0b31af0  [soaiod4]
   21     0     0     0  DL      -       0xc0b31af0  [soaiod3]
   20     0     0     0  DL      -       0xc0b31af0  [soaiod2]
   19     0     0     0  DL      -       0xc0b31af0  [soaiod1]
   18     0     0     0  DL      syncer  0xc0b32960  [syncer]
   17     0     0     0  DL      vlruwt  0xd173d388  [vnlru]
   16     0     0     0  DL      (threaded)          [bufdaemon]
100084                   D       qsleep  0xc0b31fdc  [bufdaemon]
100087                   D       -       0xc0915700  [bufspacedaemon-0]
100104                   D       sdflush 0xd2d98c84  [/ worker]
   15     0     0     0  DL      psleep  0xc0b36930  [vmdaemon]
    9     0     0     0  DL      (threaded)          [pagedaemon]
100082                   D       psleep  0xc0b36290  [dom0]
100092                   D       launds  0xc0b3629c  [laundry: dom0]
100093                   D       umarcl  0xc056eeb4  [uma]
    8     0     0     0  DL      -       0xc0939e18  [rand_harvestq]
   14     0     0     0  DL      (threaded)          [usb]
100046                   D       -       0xd280400c  [usbus0]
100047                   D       -       0xd280403c  [usbus0]
100048                   D       -       0xd280406c  [usbus0]
100049                   D       -       0xd280409c  [usbus0]
100050                   D       -       0xd28040cc  [usbus0]
100052                   D       -       0xd17a6c84  [usbus1]
100053                   D       -       0xd17a6cb4  [usbus1]
100054                   D       -       0xd17a6ce4  [usbus1]
100055                   D       -       0xd17a6d14  [usbus1]
100056                   D       -       0xd17a6d44  [usbus1]
100058                   D       -       0xd280daac  [usbus2]
100059                   D       -       0xd280dadc  [usbus2]
100060                   D       -       0xd280db0c  [usbus2]
100061                   D       -       0xd280db3c  [usbus2]
100062                   D       -       0xd280db6c  [usbus2]
100064                   D       -       0xd2838c84  [usbus3]
100065                   D       -       0xd2838cb4  [usbus3]
100066                   D       -       0xd2838ce4  [usbus3]
100067                   D       -       0xd2838d14  [usbus3]
100068                   D       -       0xd2838d44  [usbus3]
100070                   D       -       0xd284aaac  [usbus4]
100071                   D       -       0xd284aadc  [usbus4]
100072                   D       -       0xd284ab0c  [usbus4]
100073                   D       -       0xd284ab3c  [usbus4]
100074                   D       -       0xd284ab6c  [usbus4]
    7     0     0     0  DL      (threaded)          [cam]
100039                   D       -       0xc09361c0  [doneq0]
100040                   D       -       0xc0936140  [async]
100080                   D       -       0xc093606c  [scanner]
    6     0     0     0  DL      crypto_ 0xc3bbfdac  [crypto returns 3]
    5     0     0     0  DL      crypto_ 0xc3bbfd7c  [crypto returns 2]
    4     0     0     0  DL      crypto_ 0xc3bbfd4c  [crypto returns 1]
    3     0     0     0  DL      crypto_ 0xc3bbfd1c  [crypto returns 0]
    2     0     0     0  DL      crypto_ 0xc0b352ec  [crypto]
   13     0     0     0  DL      seqstat 0xd0495dcc  [sequencer 00]
   12     0     0     0  DL      (threaded)          [geom]
100026                   D       -       0xc0ab2d38  [g_event]
100027                   D       -       0xc0ab2d3c  [g_up]
100028                   D       -       0xc0ab2d40  [g_down]
   11     0     0     0  WL      (threaded)          [intr]
100010                   I                           [swi6: Giant taskq]
100016                   I                           [swi5: fast taskq]
100018                   I                           [swi6: task queue]
100019                   I                           [swi1: netisr 0]
100020                   I                           [swi4: clock (0)]
100021                   I                           [swi4: clock (1)]
100022                   I                           [swi4: clock (2)]
100023                   I                           [swi4: clock (3)]
100024                   I                           [swi3: vm]
100041                   I                           [gic0,s11: gpio0]
100042                   I                           [gic0,s45: gpio1]
100043                   I                           [gic0,s50: a31dmac0]
100044                   I                           [gic0,s60: aw_mmc0]
100045                   I                           [gic0,s71: musbotg0]
100051                   I                           [gic0,s72: ehci0]
100057                   I                           [gic0,s73: ohci0]
100063                   I                           [gic0,s78: ehci1]
100069                   I                           [gic0,s79: ohci1]
100075                   I                           [gic0,s82: awg0]
100076                   I                           [swi0: uart]
100077                   I                           [gic0,s31:-_thermal0]
100081                   I                           [gic0,s6: iichb0]
   10     0     0     0  RL      (threaded)          [idle]
100002                   Run     CPU 0               [idle: cpu0]
100003                   CanRun                      [idle: cpu1]
100004                   Run     CPU 2               [idle: cpu2]
100005                   Run     CPU 3               [idle: cpu3]
    1     0     1     0  SLs     wait    0xc29fdc40  [init]
    0     0     0     0  DLs     (threaded)          [kernel]
100000                   D       swapin  0xc0ab31c0  [swapper]
100006                   D       -       0xc3bc0400  [softirq_0]
100007                   D       -       0xc3bc0300  [softirq_1]
100008                   D       -       0xc3bc0200  [softirq_2]
100009                   D       -       0xc3bc0100  [softirq_3]
100011                   D       -       0xd0453e00  [in6m_free taskq]
100012                   D       -       0xd0453d00  [thread taskq]
100013                   D       -       0xd0453c00  [aiod_kick taskq]
100014                   D       -       0xd0453b00  [deferred_unmount ta]
100015                   D       -       0xd0453a00  [inm_free taskq]
100017                   D       -       0xd0453800  [kqueue_ctx taskq]
100025                   D       -       0xd0453600  [firmware taskq]
100030                   D       -       0xd0453500  [crypto_0]
100031                   D       -       0xd0453500  [crypto_1]
100032                   D       -       0xd0453500  [crypto_2]
100033                   D       -       0xd0453500  [crypto_3]
100079                   D       -       0xd173fa00  [CAM taskq]
100095                   D       -       0xd2cdce00  [rtwn0 net80211 task]
db>
Comment 1 Kubilay Kocak freebsd_committer freebsd_triage 2021-10-08 02:30:57 UTC
^Triage: Set Version to earliest confirmed (12.2-R)
Comment 2 Vladimir Kondratyev freebsd_committer freebsd_triage 2021-10-08 16:30:11 UTC
4 byte constant string "iic" did not pass length check for 64 byte buffer. That is strange.

You definitely have some sort of memory corruption. Through local source modification, out of buffer write or hardware failure.
Comment 3 alydiomc 2021-10-12 11:55:59 UTC
Created attachment 228624 [details]
twsi.c driver
Comment 4 alydiomc 2021-10-12 11:57:52 UTC
Comment on attachment 228624 [details]
twsi.c driver

Seems the driver does not handle 16bit wide addressing properly.

I made some modification. Looks to be working.

root@nanopi-neo:~/prog/I2C # ./i2c -s -f /dev/iic0
Scanning I2C devices on /dev/iic0: 57 68

root@nanopi-neo:~/prog/I2C # ./i2c -a 0x57 -f /dev/iic0 -d r -o 0 -w 16 -c 16 -m tr
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f

root@nanopi-neo:~/prog/I2C # echo -n "test" | ./i2c -a 0x57 -f /dev/iic0 -d w -o 0x6 -w 16 -c 4 -m tr
root@nanopi-neo:~/prog/I2C # ./i2c -a 0x57 -f /dev/iic0 -d r -o 0 -w 16 -c 16 -m tr
00 01 02 03 04 05 74 65 73 74 0a 0b 0c 0d 0e 0f

root@nanopi-neo:~/prog/I2C # date;./ds1307 -s;./ds1307 -r
Tue Oct 12 19:45:35 PST 2021
19:45:35 12/10/2021

root@nanopi-neo:~/prog/I2C # ./i2c -a 0x68 -f /dev/iic0 -d r -o 0 -w 8 -c 1 -m tr
15
root@nanopi-neo:~/prog/I2C # ./i2c -a 0x68 -f /dev/iic0 -d r -o 0 -w 8 -c 1 -m tr
16
Comment 5 alydiomc 2021-10-12 12:01:01 UTC
on i2c(8), i also adjusted the parsing of offset. Seems LSB is being sent first. I need MSB first.

off.off16 =  (((uint16_t)i2c_opt.off << 8) & 0xff00) | (((uint16_t)i2c_opt.off >> 8) & 0x00ff);
Comment 6 Vladimir Kondratyev freebsd_committer freebsd_triage 2021-10-13 07:13:26 UTC
Could upload it as a diff against base version rather than entire content
Comment 7 alydiomc 2021-10-13 10:31:36 UTC
(In reply to Vladimir Kondratyev from comment #6)

Yeah! Sorry, this is my first. :)  

Will do next time. Thank you!
Comment 8 alydiomc 2021-10-19 07:39:47 UTC
Created attachment 228827 [details]
Added some improvements.

root@nanopi-neo:~/i2c # i2c -s /dev/iic0
Scanning I2C devices on /dev/iic0: 40 57 68 

[8bit single write] 
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d w -o 0 -w 8 -c 1 -m tr < 00.hex
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d r -o 0 -w 8 -c 1 -m tr
00

[8bit single write] 
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d w -o 0 -w 8 -c 1 -m tr < 20.hex
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d r -o 0 -w 8 -c 1 -m tr
20 

[8bit multiple write]  Clear Registers from offset 5 to 1f [27 bytes]
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d w -o 5 -w 8 -c 27 -m tr < null.txt

[8bit multiple Read] Read Registers from offset 0 [48 bytes]
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d r -o 0 -w 8 -c 48 -m tr
20 13 44 4c 46 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
ff 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 

[8bit multiple write] Fill Register from offset 5 to 1f [27 bytes]
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d w -o 5 -w 8 -c 27 -m tr < random.txt
root@nanopi-neo:~/i2c # i2c -a 40 -f /dev/iic0 -d r -o 0 -w 8 -c 48 -m tr
20 13 44 4c 46 7e 77 14 67 01 58 1c 2b 06 0e 17 
69 10 1e 1f 2e 00 c6 16 0c 04 a2 04 3c 06 1e 11 
ff 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 

[16bit write] Clear eeprom data from offset 0 to 1F [32 bytes]
root@nanopi-neo:~/i2c # i2c -a 57 -f /dev/iic0 -d w -o 0 -w 16 -c 32 -m tr < null.txt

[16bit Read] Read eeprom data from offset 0 [48 bytes]
root@nanopi-neo:~/i2c # i2c -a 57 -f /dev/iic0 -d r -o 0 -w 16 -c 48 -m tr
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
f8 0c 00 00 02 04 00 05 34 00 20 00 08 00 28 00 

[16bit  write] Fill eeprom from offset 0, 32bytes
root@nanopi-neo:~/i2c # i2c -a 57 -f /dev/iic0 -d w -o 0 -w 16 -c 32 -m tr < random.txt
root@nanopi-neo:~/i2c # i2c -a 57 -f /dev/iic0 -d r -o 0 -w 16 -c 48 -m tr
7e 77 b4 67 e1 58 1c 2b a6 0e d7 69 50 1e 9f 2e 
a0 c6 76 0c 84 a2 a4 3c 66 1e 51 b4 10 f1 d8 60 
f8 0c 00 00 02 04 00 05 34 00 20 00 08 00 28 00
Comment 9 Andriy Gapon freebsd_committer freebsd_triage 2021-10-22 08:38:42 UTC
FWIW, I've been also working on twsi a little bit.
I used a bunch of I2C peripherals and had to write new drivers for a couple of devices.  I found that twsi was either too limiting or buggy with some valid protocol sequences needed for those peripherals.

My work can be found here:
https://github.com/avg-I/freebsd/commit/1c6777dc1d2ee5ba9e8ff887e9517c58340ce457
https://github.com/avg-I/freebsd/commit/35f319546b594a6094a86bcb18e415d4de2643e2
https://github.com/avg-I/freebsd/commit/5f2d7e7c13f53bfe51644fd0e1757623ca0d7990
https://github.com/avg-I/freebsd/commit/4fc6103770cf48b12c6de275b8c200df0080210a
https://github.com/avg-I/freebsd/commit/0075e711e23cc20d7a4d31cf97648c20df8c9ef3
https://github.com/avg-I/freebsd/commit/937a86158404fe84d8135110e01dd60b1e6df81b
Comment 10 alydiomc 2021-10-23 13:59:17 UTC
(In reply to Andriy Gapon from comment #9)
Hi Andriy,

Been searching a for a patch on twsi.c but couldn't find before. Thank you for sharing your works!

I tested some of your commits, below are the results:

1c6777dc1d2ee5ba9e8ff887e9517c58340ce457
   - 8bit single byte  write not working
   - eeprom write not working

35f319546b594a6094a86bcb18e415d4de2643e2
   -eeprom (16bit addressing) single byte read/write working
   -eeprom (16bit addressing) continues read/write working
   -8bit single byte read/write working
   -8bit continues read/write working

937a86158404fe84d8135110e01dd60b1e6df81b
  -can't write eeprom
Comment 11 Vladimir Kondratyev freebsd_committer freebsd_triage 2021-11-07 21:39:32 UTC
(In reply to Andriy Gapon from comment #9)
Hi Andriy,

Could you handle this PR? I do not have any twsi(4) hardware or driver internals knowledge.
Comment 12 Andriy Gapon freebsd_committer freebsd_triage 2021-11-10 14:11:09 UTC
(In reply to Vladimir Kondratyev from comment #11)
Yes, I am trying as much as my spare time allows.
Comment 13 Andriy Gapon freebsd_committer freebsd_triage 2021-11-10 14:12:48 UTC
(In reply to alydiomc from comment #10)
Did you try each of those commits individually (in isolation) ?
Or did you apply them sequentially (accumulated the changes) ?
Or something else?

Each commit has its own purpose as described in their commit messages.
Comment 14 alydiomc 2021-11-11 15:00:35 UTC
(In reply to Andriy Gapon from comment #13)
Hi Andriy,

I downloaded the "raw" file individually and then recompiled the kernel.  

Regards,
Alyd
Comment 15 Andriy Gapon freebsd_committer freebsd_triage 2021-11-11 16:26:48 UTC
(In reply to alydiomc from comment #14)
So, you did all of them one by one in isolation from each other?
Comment 16 alydiomc 2021-11-11 22:00:45 UTC
(In reply to Andriy Gapon from comment #15)
Hi Andriy,
Yes, I tested them separately but only the three commits below:
1c6777dc1d2ee5ba9e8ff887e9517c58340ce457
35f319546b594a6094a86bcb18e415d4de2643e2
937a86158404fe84d8135110e01dd60b1e6df81b

Steps:
1. download raw file.
2. copied to ${SRCROOT}/sys/dev/iicbus/twsi/twsi.c
3. rebuild
4. test
Comment 17 commit-hook freebsd_committer freebsd_triage 2021-11-26 14:25:01 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=04622a7f21157827fe75276a4520a52d3a571a86

commit 04622a7f21157827fe75276a4520a52d3a571a86
Author:     Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 08:07:27 +0000
Commit:     Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-11-26 14:17:24 +0000

    twsi: move handling of TWSI_CONTROL_ACK into the state machine

    Previously the code set TWSI_CONTROL_ACK in twsi_transfer() based on
    whether the first message had a length of one.  That was done regardless
    of whether the message was a read or write and what kind of messages
    followed it.
    Now the bit is set or cleared while handling TWSI_STATUS_ADDR_R_ACK
    state transition based on the current (read) message.

    The old code did not correctly work in a scenario where a single byte
    was read from an EEPROM device with two byte addressing.
    For example:
        i2c -m tr -a 0x50 -d r -w 16 -o 0 -c 1 -v
    The reason is that the first message (a write) has two bytes, so
    TWSI_CONTROL_ACK was set and never cleared.
    Since the controller did not send NACK the EEPROM sent more data resulting
    in a buffer overrun.

    While working on TWSI_STATUS_ADDR_R_ACK I also added support for
    the zero-length read access and then I did the same for zero-length write
    access.
    While rare, those types of I2C transactions are completely valid and are
    used by some devices.

    PR:             258994
    MFC after:      3 weeks

 sys/dev/iicbus/twsi/twsi.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)
Comment 18 commit-hook freebsd_committer freebsd_triage 2021-11-26 14:25:02 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=ff1e8581806f70e54fecddf8a6a23488dc7b968a

commit ff1e8581806f70e54fecddf8a6a23488dc7b968a
Author:     Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 09:48:21 +0000
Commit:     Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-11-26 14:20:27 +0000

    twsi: support more message combinations in transfers

    Most prominently, add support for a transfer where a write with no-stop
    flag is followed by a write with no-start flag.  Logically, it's a
    single larger write, but consumers may want to split it like that
    because one part can be a register ID and the other part can be data to
    be written to (or starting at) that register.

    Such a transfer can be created by i2c tool and iic(4) driver, e.g., for
    an EEPROM write at specific offset:
        i2c -m tr -a 0x50 -d w -w 16 -o 0 -c 8 -v < /dev/random

    This should be fixed by new code that handles the end of data transfer
    for both reads and writes.  It handles two existing conditions and one
    new.  Namely:
    - the last message has been completed -- end of transfer;
    - a message has been completed and the next one requires the start
      condition;
    - a message has been completed and the next one should be sent without
      the start condition.

    In the last case we simply switch to the next message and start sending
    its data.  Reads without the start condition are not supported yet,
    though.  That's because we NACK the last byte of the previous message,
    so the device stops sending data.  To fix this we will need to add a
    look-ahead at the next message when handling the penultimate byte of the
    current one.

    This change also fixed a bug where msg_idx was not incremented after a
    read message.  Apparently, typically a read message is a last message in
    a transfer, so the bug did not cause much trouble.

    PR:             258994
    MFC after:      3 weeks

 sys/dev/iicbus/twsi/twsi.c | 85 +++++++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 32 deletions(-)
Comment 19 commit-hook freebsd_committer freebsd_triage 2021-12-17 07:32:16 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=c7bf34cfe52c09abf813c784a60d7d9677afb603

commit c7bf34cfe52c09abf813c784a60d7d9677afb603
Author:     Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 08:07:27 +0000
Commit:     Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-12-17 07:30:41 +0000

    twsi: move handling of TWSI_CONTROL_ACK into the state machine

    Previously the code set TWSI_CONTROL_ACK in twsi_transfer() based on
    whether the first message had a length of one.  That was done regardless
    of whether the message was a read or write and what kind of messages
    followed it.
    Now the bit is set or cleared while handling TWSI_STATUS_ADDR_R_ACK
    state transition based on the current (read) message.

    The old code did not correctly work in a scenario where a single byte
    was read from an EEPROM device with two byte addressing.
    For example:
        i2c -m tr -a 0x50 -d r -w 16 -o 0 -c 1 -v
    The reason is that the first message (a write) has two bytes, so
    TWSI_CONTROL_ACK was set and never cleared.
    Since the controller did not send NACK the EEPROM sent more data resulting
    in a buffer overrun.

    While working on TWSI_STATUS_ADDR_R_ACK I also added support for
    the zero-length read access and then I did the same for zero-length write
    access.
    While rare, those types of I2C transactions are completely valid and are
    used by some devices.

    PR:             258994

    (cherry picked from commit 04622a7f21157827fe75276a4520a52d3a571a86)

 sys/dev/iicbus/twsi/twsi.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)
Comment 20 commit-hook freebsd_committer freebsd_triage 2021-12-17 07:32:17 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=6820d578bb1fb8d0a8e781a7f3d59311a35d453f

commit 6820d578bb1fb8d0a8e781a7f3d59311a35d453f
Author:     Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 09:48:21 +0000
Commit:     Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-12-17 07:30:58 +0000

    twsi: support more message combinations in transfers

    Most prominently, add support for a transfer where a write with no-stop
    flag is followed by a write with no-start flag.  Logically, it's a
    single larger write, but consumers may want to split it like that
    because one part can be a register ID and the other part can be data to
    be written to (or starting at) that register.

    Such a transfer can be created by i2c tool and iic(4) driver, e.g., for
    an EEPROM write at specific offset:
        i2c -m tr -a 0x50 -d w -w 16 -o 0 -c 8 -v < /dev/random

    This should be fixed by new code that handles the end of data transfer
    for both reads and writes.  It handles two existing conditions and one
    new.  Namely:
    - the last message has been completed -- end of transfer;
    - a message has been completed and the next one requires the start
      condition;
    - a message has been completed and the next one should be sent without
      the start condition.

    In the last case we simply switch to the next message and start sending
    its data.  Reads without the start condition are not supported yet,
    though.  That's because we NACK the last byte of the previous message,
    so the device stops sending data.  To fix this we will need to add a
    look-ahead at the next message when handling the penultimate byte of the
    current one.

    This change also fixed a bug where msg_idx was not incremented after a
    read message.  Apparently, typically a read message is a last message in
    a transfer, so the bug did not cause much trouble.

    PR:             258994

    (cherry picked from commit ff1e8581806f70e54fecddf8a6a23488dc7b968a)

 sys/dev/iicbus/twsi/twsi.c | 85 +++++++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 32 deletions(-)
Comment 21 commit-hook freebsd_committer freebsd_triage 2021-12-17 07:32:18 UTC
A commit in branch stable/12 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=074248b948b6fab3ec3a84e2573201fe82190cf3

commit 074248b948b6fab3ec3a84e2573201fe82190cf3
Author:     Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 08:07:27 +0000
Commit:     Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-12-17 07:31:21 +0000

    twsi: move handling of TWSI_CONTROL_ACK into the state machine

    Previously the code set TWSI_CONTROL_ACK in twsi_transfer() based on
    whether the first message had a length of one.  That was done regardless
    of whether the message was a read or write and what kind of messages
    followed it.
    Now the bit is set or cleared while handling TWSI_STATUS_ADDR_R_ACK
    state transition based on the current (read) message.

    The old code did not correctly work in a scenario where a single byte
    was read from an EEPROM device with two byte addressing.
    For example:
        i2c -m tr -a 0x50 -d r -w 16 -o 0 -c 1 -v
    The reason is that the first message (a write) has two bytes, so
    TWSI_CONTROL_ACK was set and never cleared.
    Since the controller did not send NACK the EEPROM sent more data resulting
    in a buffer overrun.

    While working on TWSI_STATUS_ADDR_R_ACK I also added support for
    the zero-length read access and then I did the same for zero-length write
    access.
    While rare, those types of I2C transactions are completely valid and are
    used by some devices.

    PR:             258994

    (cherry picked from commit 04622a7f21157827fe75276a4520a52d3a571a86)

 sys/dev/iicbus/twsi/twsi.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)
Comment 22 commit-hook freebsd_committer freebsd_triage 2021-12-17 07:32:19 UTC
A commit in branch stable/12 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=e8dbe7bdcf5d9dfbe40b326001b7751e3d42c635

commit e8dbe7bdcf5d9dfbe40b326001b7751e3d42c635
Author:     Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 09:48:21 +0000
Commit:     Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-12-17 07:31:39 +0000

    twsi: support more message combinations in transfers

    Most prominently, add support for a transfer where a write with no-stop
    flag is followed by a write with no-start flag.  Logically, it's a
    single larger write, but consumers may want to split it like that
    because one part can be a register ID and the other part can be data to
    be written to (or starting at) that register.

    Such a transfer can be created by i2c tool and iic(4) driver, e.g., for
    an EEPROM write at specific offset:
        i2c -m tr -a 0x50 -d w -w 16 -o 0 -c 8 -v < /dev/random

    This should be fixed by new code that handles the end of data transfer
    for both reads and writes.  It handles two existing conditions and one
    new.  Namely:
    - the last message has been completed -- end of transfer;
    - a message has been completed and the next one requires the start
      condition;
    - a message has been completed and the next one should be sent without
      the start condition.

    In the last case we simply switch to the next message and start sending
    its data.  Reads without the start condition are not supported yet,
    though.  That's because we NACK the last byte of the previous message,
    so the device stops sending data.  To fix this we will need to add a
    look-ahead at the next message when handling the penultimate byte of the
    current one.

    This change also fixed a bug where msg_idx was not incremented after a
    read message.  Apparently, typically a read message is a last message in
    a transfer, so the bug did not cause much trouble.

    PR:             258994

    (cherry picked from commit ff1e8581806f70e54fecddf8a6a23488dc7b968a)

 sys/dev/iicbus/twsi/twsi.c | 85 +++++++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 32 deletions(-)
Comment 23 Andriy Gapon freebsd_committer freebsd_triage 2021-12-17 07:34:16 UTC
Should be fixed in the stable branches now.
Please re-test.