tpm_tis_spi: Release chip select when flow control fails
authorPeijie Shao <shaopeijie@cestc.cn>
Tue, 23 May 2023 02:45:36 +0000 (10:45 +0800)
committerJarkko Sakkinen <jarkko@kernel.org>
Mon, 17 Jul 2023 19:32:30 +0000 (19:32 +0000)
The failure paths in tpm_tis_spi_transfer() do not deactivate
chip select. Send an empty message (cs_select == 0) to overcome
this.

The patch is tested by two ways.
One way needs to touch hardware:
   1. force pull MISO pin down to GND, it emulates a forever
      'WAIT' timing.
   2. probe cs pin by an oscilloscope.
   3. load tpm_tis_spi.ko.
After loading, dmesg prints:
    "probe of spi0.0 failed with error -110"
and oscilloscope shows cs pin goes high(deactivated) after
the failure. Before the patch, cs pin keeps low.

Second way is by writing a fake spi controller.
   1. implement .transfer_one method, fill all rx buf with 0.
   2. implement .set_cs method, print the state of cs pin.
   we can see cs goes high after the failure.

Signed-off-by: Peijie Shao <shaopeijie@cestc.cn>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
drivers/char/tpm/tpm_tis_spi_main.c

index 1f52079..9bfaba0 100644 (file)
@@ -136,6 +136,14 @@ int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
        }
 
 exit:
+       if (ret < 0) {
+               /* Deactivate chip select */
+               memset(&spi_xfer, 0, sizeof(spi_xfer));
+               spi_message_init(&m);
+               spi_message_add_tail(&spi_xfer, &m);
+               spi_sync_locked(phy->spi_device, &m);
+       }
+
        spi_bus_unlock(phy->spi_device->master);
        return ret;
 }