brintos

brintos / linux-shallow public Read only

0
0
Text · 6.0 KiB · 91d2388 Raw
137 lines · plain
1=========================2Linux I2C fault injection3=========================4 5The GPIO based I2C bus master driver can be configured to provide fault6injection capabilities. It is then meant to be connected to another I2C bus7which is driven by the I2C bus master driver under test. The GPIO fault8injection driver can create special states on the bus which the other I2C bus9master driver should handle gracefully.10 11Once the Kconfig option I2C_GPIO_FAULT_INJECTOR is enabled, there will be an12'i2c-fault-injector' subdirectory in the Kernel debugfs filesystem, usually13mounted at /sys/kernel/debug. There will be a separate subdirectory per GPIO14driven I2C bus. Each subdirectory will contain files to trigger the fault15injection. They will be described now along with their intended use-cases.16 17Wire states18===========19 20"scl"21-----22 23By reading this file, you get the current state of SCL. By writing, you can24change its state to either force it low or to release it again. So, by using25"echo 0 > scl" you force SCL low and thus, no communication will be possible26because the bus master under test will not be able to clock. It should detect27the condition of SCL being unresponsive and report an error to the upper28layers.29 30"sda"31-----32 33By reading this file, you get the current state of SDA. By writing, you can34change its state to either force it low or to release it again. So, by using35"echo 0 > sda" you force SDA low and thus, data cannot be transmitted. The bus36master under test should detect this condition and trigger a bus recovery (see37I2C specification version 4, section 3.1.16) using the helpers of the Linux I2C38core (see 'struct bus_recovery_info'). However, the bus recovery will not39succeed because SDA is still pinned low until you manually release it again40with "echo 1 > sda". A test with an automatic release can be done with the41"incomplete transfers" class of fault injectors.42 43Incomplete transfers44====================45 46The following fault injectors create situations where SDA will be held low by a47device. Bus recovery should be able to fix these situations. But please note:48there are I2C client devices which detect a stuck SDA on their side and release49it on their own after a few milliseconds. Also, there might be an external50device deglitching and monitoring the I2C bus. It could also detect a stuck SDA51and will init a bus recovery on its own. If you want to implement bus recovery52in a bus master driver, make sure you checked your hardware setup for such53devices before. And always verify with a scope or logic analyzer!54 55"incomplete_address_phase"56--------------------------57 58This file is write only and you need to write the address of an existing I2C59client device to it. Then, a read transfer to this device will be started, but60it will stop at the ACK phase after the address of the client has been61transmitted. Because the device will ACK its presence, this results in SDA62being pulled low by the device while SCL is high. So, similar to the "sda" file63above, the bus master under test should detect this condition and try a bus64recovery. This time, however, it should succeed and the device should release65SDA after toggling SCL.66 67"incomplete_write_byte"68-----------------------69 70Similar to above, this file is write only and you need to write the address of71an existing I2C client device to it.72 73The injector will again stop at one ACK phase, so the device will keep SDA low74because it acknowledges data. However, there are two differences compared to75'incomplete_address_phase':76 77a) the message sent out will be a write message78b) after the address byte, a 0x00 byte will be transferred. Then, stop at ACK.79 80This is a highly delicate state, the device is set up to write any data to81register 0x00 (if it has registers) when further clock pulses happen on SCL.82This is why bus recovery (up to 9 clock pulses) must either check SDA or send83additional STOP conditions to ensure the bus has been released. Otherwise84random data will be written to a device!85 86Lost arbitration87================88 89Here, we want to simulate the condition where the master under test loses the90bus arbitration against another master in a multi-master setup.91 92"lose_arbitration"93------------------94 95This file is write only and you need to write the duration of the arbitration96interference (in µs, maximum is 100ms). The calling process will then sleep97and wait for the next bus clock. The process is interruptible, though.98 99Arbitration lost is achieved by waiting for SCL going down by the master under100test and then pulling SDA low for some time. So, the I2C address sent out101should be corrupted and that should be detected properly. That means that the102address sent out should have a lot of '1' bits to be able to detect corruption.103There doesn't need to be a device at this address because arbitration lost104should be detected beforehand. Also note, that SCL going down is monitored105using interrupts, so the interrupt latency might cause the first bits to be not106corrupted. A good starting point for using this fault injector on an otherwise107idle bus is::108 109  # echo 200 > lose_arbitration &110  # i2cget -y <bus_to_test> 0x3f111 112Panic during transfer113=====================114 115This fault injector will create a Kernel panic once the master under test116started a transfer. This usually means that the state machine of the bus master117driver will be ungracefully interrupted and the bus may end up in an unusual118state. Use this to check if your shutdown/reboot/boot code can handle this119scenario.120 121"inject_panic"122--------------123 124This file is write only and you need to write the delay between the detected125start of a transmission and the induced Kernel panic (in µs, maximum is 100ms).126The calling process will then sleep and wait for the next bus clock. The127process is interruptible, though.128 129Start of a transfer is detected by waiting for SCL going down by the master130under test.  A good starting point for using this fault injector is::131 132  # echo 0 > inject_panic &133  # i2cget -y <bus_to_test> <some_address>134 135Note that there doesn't need to be a device listening to the address you are136using. Results may vary depending on that, though.137