1. 19 3月, 2020 7 次提交
    • V
      spi: spi-fsl-dspi: Avoid NULL pointer in dspi_slave_abort for non-DMA mode · 3d6224e6
      Vladimir Oltean 提交于
      The driver does not create the dspi->dma structure unless operating in
      DSPI_DMA_MODE, so it makes sense to check for that.
      
      Fixes: f4b32390 ("spi: Introduce dspi_slave_abort() function for NXP's dspi SPI driver")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-8-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      3d6224e6
    • V
      spi: spi-fsl-dspi: Replace interruptible wait queue with a simple completion · 4f5ee75e
      Vladimir Oltean 提交于
      Currently the driver puts the process in interruptible sleep waiting for
      the interrupt train to finish transfer to/from the tx_buf and rx_buf.
      
      But exiting the process with ctrl-c may make the kernel panic: the
      wait_event_interruptible call will return -ERESTARTSYS, which a proper
      driver implementation is perhaps supposed to handle, but nonetheless
      this one doesn't, and aborts the transfer altogether.
      
      Actually when the task is interrupted, there is still a high chance that
      the dspi_interrupt is still triggering. And if dspi_transfer_one_message
      returns execution all the way to the spi_device driver, that can free
      the spi_message and spi_transfer structures, leaving the interrupts to
      access a freed tx_buf and rx_buf.
      
      hexdump -C /dev/mtd0
      00000000  00 75 68 75 0a ff ff ff  ff ff ff ff ff ff ff ff
      |.uhu............|
      00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
      |................|
      *
      ^C[   38.495955] fsl-dspi 2120000.spi: Waiting for transfer to complete failed!
      [   38.503097] spi_master spi2: failed to transfer one message from queue
      [   38.509729] Unable to handle kernel paging request at virtual address ffff800095ab3377
      [   38.517676] Mem abort info:
      [   38.520474]   ESR = 0x96000045
      [   38.523533]   EC = 0x25: DABT (current EL), IL = 32 bits
      [   38.528861]   SET = 0, FnV = 0
      [   38.531921]   EA = 0, S1PTW = 0
      [   38.535067] Data abort info:
      [   38.537952]   ISV = 0, ISS = 0x00000045
      [   38.541797]   CM = 0, WnR = 1
      [   38.544771] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000082621000
      [   38.551494] [ffff800095ab3377] pgd=00000020fffff003, p4d=00000020fffff003, pud=0000000000000000
      [   38.560229] Internal error: Oops: 96000045 [#1] PREEMPT SMP
      [   38.565819] Modules linked in:
      [   38.568882] CPU: 0 PID: 2729 Comm: hexdump Not tainted 5.6.0-rc4-next-20200306-00052-gd8730cdc8a0b-dirty #193
      [   38.578834] Hardware name: Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier (DT)
      [   38.587129] pstate: 20000085 (nzCv daIf -PAN -UAO)
      [   38.591941] pc : ktime_get_real_ts64+0x3c/0x110
      [   38.596487] lr : spi_take_timestamp_pre+0x40/0x90
      [   38.601203] sp : ffff800010003d90
      [   38.604525] x29: ffff800010003d90 x28: ffff80001200e000
      [   38.609854] x27: ffff800011da9000 x26: ffff002079c40400
      [   38.615184] x25: ffff8000117fe018 x24: ffff800011daa1a0
      [   38.620513] x23: ffff800015ab3860 x22: ffff800095ab3377
      [   38.625841] x21: 000000000000146e x20: ffff8000120c3000
      [   38.631170] x19: ffff0020795f6e80 x18: ffff800011da9948
      [   38.636498] x17: 0000000000000000 x16: 0000000000000000
      [   38.641826] x15: ffff800095ab3377 x14: 0720072007200720
      [   38.647155] x13: 0720072007200765 x12: 0775076507750771
      [   38.652483] x11: 0720076d076f0772 x10: 0000000000000040
      [   38.657812] x9 : ffff8000108e2100 x8 : ffff800011dcabe8
      [   38.663139] x7 : 0000000000000000 x6 : ffff800015ab3a60
      [   38.668468] x5 : 0000000007200720 x4 : ffff800095ab3377
      [   38.673796] x3 : 0000000000000000 x2 : 0000000000000ab0
      [   38.679125] x1 : ffff800011daa000 x0 : 0000000000000026
      [   38.684454] Call trace:
      [   38.686905]  ktime_get_real_ts64+0x3c/0x110
      [   38.691100]  spi_take_timestamp_pre+0x40/0x90
      [   38.695470]  dspi_fifo_write+0x58/0x2c0
      [   38.699315]  dspi_interrupt+0xbc/0xd0
      [   38.702987]  __handle_irq_event_percpu+0x78/0x2c0
      [   38.707706]  handle_irq_event_percpu+0x3c/0x90
      [   38.712161]  handle_irq_event+0x4c/0xd0
      [   38.716008]  handle_fasteoi_irq+0xbc/0x170
      [   38.720115]  generic_handle_irq+0x2c/0x40
      [   38.724135]  __handle_domain_irq+0x68/0xc0
      [   38.728243]  gic_handle_irq+0xc8/0x160
      [   38.732000]  el1_irq+0xb8/0x180
      [   38.735149]  spi_nor_spimem_read_data+0xe0/0x140
      [   38.739779]  spi_nor_read+0xc4/0x120
      [   38.743364]  mtd_read_oob+0xa8/0xc0
      [   38.746860]  mtd_read+0x4c/0x80
      [   38.750007]  mtdchar_read+0x108/0x2a0
      [   38.753679]  __vfs_read+0x20/0x50
      [   38.757002]  vfs_read+0xa4/0x190
      [   38.760237]  ksys_read+0x6c/0xf0
      [   38.763471]  __arm64_sys_read+0x20/0x30
      [   38.767319]  el0_svc_common.constprop.3+0x90/0x160
      [   38.772125]  do_el0_svc+0x28/0x90
      [   38.775449]  el0_sync_handler+0x118/0x190
      [   38.779468]  el0_sync+0x140/0x180
      [   38.782793] Code: 91000294 1400000f d50339bf f9405e80 (f90002c0)
      [   38.788910] ---[ end trace 55da560db4d6bef7 ]---
      [   38.793540] Kernel panic - not syncing: Fatal exception in interrupt
      [   38.799914] SMP: stopping secondary CPUs
      [   38.803849] Kernel Offset: disabled
      [   38.807344] CPU features: 0x10002,20006008
      [   38.811451] Memory Limit: none
      [   38.814513] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
      
      So it is clear that the "interruptible" part isn't handled correctly.
      When the process receives a signal, one could either attempt a clean
      abort (which appears to be difficult with this hardware) or just keep
      restarting the sleep until the wait queue really completes. But checking
      in a loop for -ERESTARTSYS is a bit too complicated for this driver, so
      just make the sleep uninterruptible, to avoid all that nonsense.
      
      The wait queue was actually restructured as a completion, after polling
      other drivers for the most "popular" approach.
      
      Fixes: 349ad66c ("spi:Add Freescale DSPI driver for Vybrid VF610 platform")
      Reported-by: NMichael Walle <michael@walle.cc>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-7-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      4f5ee75e
    • V
      spi: spi-fsl-dspi: Protect against races on dspi->words_in_flight · 0dedf901
      Vladimir Oltean 提交于
      dspi->words_in_flight is a variable populated in the *_write functions
      and used in the dspi_fifo_read function. It is also used in
      dspi_fifo_write, immediately after transmission, to update the
      message->actual_length variable used by higher layers such as spi-mem
      for integrity checking.
      
      But it may happen that the IRQ which calls dspi_fifo_read to be
      triggered before the updating of message->actual_length takes place. In
      that case, dspi_fifo_read will decrement dspi->words_in_flight to -1,
      and that will cause an invalid modification of message->actual_length.
      
      For that, we make the simplest fix possible: to not decrement the actual
      shared variable in dspi->words_in_flight from dspi_fifo_read, but
      actually a copy of it which is on stack.
      
      But even if dspi_fifo_read from the next IRQ does not interfere with the
      dspi_fifo_write of the current chunk, the *next* dspi_fifo_write still
      can. So we must assume that everything after the last write to the TX
      FIFO can be preempted by the "TX complete" IRQ, and the dspi_fifo_write
      function must be safe against that. This means refactoring the 2
      flavours of FIFO writes (for EOQ and XSPI) such that the calculation of
      the number of words to be written is common and happens a priori. This
      way, the code for updating the message->actual_length variable works
      with a copy and not with the volatile dspi->words_in_flight.
      
      After some interior debate, the dspi->progress variable used for
      software timestamping was *not* backed up against preemption in a copy
      on stack. Because if preemption does occur between
      spi_take_timestamp_pre and spi_take_timestamp_post, there's really no
      point in trying to save anything. The first-in-time
      spi_take_timestamp_post call with a dspi->progress higher than the
      requested xfer->ptp_sts_word_post will trigger xfer->timestamped = true
      anyway and will close the deal.
      
      To understand the above a bit better, consider a transfer with
      xfer->ptp_sts_word_pre = xfer->ptp_sts_word_post = 3, and
      xfer->bits_per_words = 8 (so byte 3 needs to be timestamped). The DSPI
      controller timestamps in chunks of 4 bytes at a time, and preemption
      occurs in the middle of timestamping the first chunk:
      
        spi_take_timestamp_pre(0)
          .
          . (preemption)
          .
          . spi_take_timestamp_pre(4)
          .
          . spi_take_timestamp_post(7)
          .
        spi_take_timestamp_post(3)
      
      So the reason I'm not bothering to back up dspi->progress for that
      spi_take_timestamp_post(3) is that spi_take_timestamp_post(7) is going
      to (a) be more honest, (b) provide better accuracy and (c) already
      render the spi_take_timestamp_post(3) into a noop by setting
      xfer->timestamped = true anyway.
      
      Fixes: d59c90a2 ("spi: spi-fsl-dspi: Convert TCFQ users to XSPI FIFO mode")
      Reported-by: NMichael Walle <michael@walle.cc>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-6-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      0dedf901
    • V
      spi: spi-fsl-dspi: Avoid reading more data than written in EOQ mode · c6c1e30a
      Vladimir Oltean 提交于
      If dspi->words_in_flight is populated with the hardware FIFO size,
      then in dspi_fifo_read it will attempt to read more data at the end of a
      buffer that is not a multiple of 16 bytes in length. It will probably
      time out attempting to do so.
      
      So limit the num_fifo_entries variable to the actual number of FIFO
      entries that is going to be used.
      
      Fixes: d59c90a2 ("spi: spi-fsl-dspi: Convert TCFQ users to XSPI FIFO mode")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-5-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      c6c1e30a
    • V
      spi: spi-fsl-dspi: Fix bits-per-word acceleration in DMA mode · a957499b
      Vladimir Oltean 提交于
      In DMA mode, dspi_setup_accel does not get called, which results in the
      dspi->oper_word_size variable (which is used by dspi_dma_xfer) to not be
      initialized properly.
      
      Because oper_word_size is zero, a few calculations end up being
      incorrect, and the DMA transfer eventually times out instead of sending
      anything on the wire.
      
      Set up native transfers (or 8-on-16 acceleration) using dspi_setup_accel
      for DMA mode too.
      
      Also take the opportunity and simplify the DMA buffer handling a little
      bit.
      
      Fixes: 6c1c26ec ("spi: spi-fsl-dspi: Accelerate transfers using larger word size if possible")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-4-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      a957499b
    • V
      spi: spi-fsl-dspi: Fix little endian access to PUSHR CMD and TXDATA · 671ffde1
      Vladimir Oltean 提交于
      In XSPI mode, the 32-bit PUSHR register can be written to separately:
      the higher 16 bits are for commands and the lower 16 bits are for data.
      
      This has nicely been hacked around, by defining a second regmap with a
      width of 16 bits, and effectively splitting a 32-bit register into 2
      16-bit ones, from the perspective of this regmap_pushr.
      
      The problem is the assumption about the controller's endianness. If the
      controller is little endian (such as anything post-LS1046A), then the
      first 2 bytes, in the order imposed by memory layout, will actually hold
      the TXDATA, and the last 2 bytes will hold the CMD.
      
      So take the controller's endianness into account when performing split
      writes to PUSHR. The obvious and simple solution would have been to call
      regmap_get_val_endian(), but that is an internal regmap function and we
      don't want to change regmap just for this. Therefore, we just re-read
      the "big-endian" device tree property.
      
      Fixes: 58ba07ec ("spi: spi-fsl-dspi: Add support for XSPI mode registers")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-3-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      671ffde1
    • V
      spi: spi-fsl-dspi: Don't access reserved fields in SPI_MCR · 4fcc7c22
      Vladimir Oltean 提交于
      The SPI_MCR_PCSIS macro assumes that the controller has a number of chip
      select signals equal to 6. That is not always the case, but actually is
      described through the driver-specific "spi-num-chipselects" device tree
      binding. LS1028A for example only has 4 chip selects.
      
      Don't write to the upper bits of the PCSIS field, which are reserved in
      the reference manual.
      
      Fixes: 349ad66c ("spi:Add Freescale DSPI driver for Vybrid VF610 platform")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Tested-by: NMichael Walle <michael@walle.cc>
      Link: https://lore.kernel.org/r/20200318001603.9650-2-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      4fcc7c22
  2. 11 3月, 2020 1 次提交
  3. 05 3月, 2020 17 次提交
  4. 31 12月, 2019 1 次提交
    • V
      spi: spi-fsl-dspi: Fix 16-bit word order in 32-bit XSPI mode · ca59d5a5
      Vladimir Oltean 提交于
      When used in Extended SPI mode on LS1021A, the DSPI controller wants to
      have the least significant 16-bit word written first to the TX FIFO.
      
      In fact, the LS1021A reference manual says:
      
      33.5.2.4.2 Draining the TX FIFO
      
      When Extended SPI Mode (DSPIx_MCR[XSPI]) is enabled, if the frame size
      of SPI Data to be transmitted is more than 16 bits, then it causes two
      Data entries to be popped from TX FIFO simultaneously which are
      transferred to the shift register. The first of the two popped entries
      forms the 16 least significant bits of the SPI frame to be transmitted.
      
      So given the following TX buffer:
      
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
       | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | 0x7 | 0x8 | 0x9 | 0xa | 0xb |
       +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
       |     32-bit word 1     |     32-bit word 2     |     32-bit word 3     |
       +-----------------------+-----------------------+-----------------------+
      
      The correct way that a little-endian system should transmit it on the
      wire when bits_per_word is 32 is:
      
      0x03020100
      0x07060504
      0x0b0a0908
      
      But it is actually transmitted as following, as seen with a scope:
      
      0x01000302
      0x05040706
      0x09080b0a
      
      It appears that this patch has been submitted at least once before:
      https://lkml.org/lkml/2018/9/21/286
      but in that case Chuanhua Han did not manage to explain the problem
      clearly enough and the patch did not get merged, leaving XSPI mode
      broken.
      
      Fixes: 8fcd151d ("spi: spi-fsl-dspi: XSPI FIFO handling (in TCFQ mode)")
      Cc: Esben Haabendal <eha@deif.com>
      Cc: Chuanhua Han <chuanhua.han@nxp.com>
      Signed-off-by: NVladimir Oltean <olteanv@gmail.com>
      Link: https://lore.kernel.org/r/20191228135536.14284-1-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      Cc: stable@vger.kernel.org
      ca59d5a5
  5. 28 12月, 2019 1 次提交
  6. 16 12月, 2019 1 次提交
  7. 15 10月, 2019 1 次提交
  8. 08 10月, 2019 2 次提交
    • V
      spi: spi-fsl-dspi: Always use the TCFQ devices in poll mode · 5d2af8bc
      Vladimir Oltean 提交于
      With this patch, the "interrupts" property from the device tree bindings
      is ignored, even if present, if the driver runs in TCFQ mode.
      
      Switching to using the DSPI in poll mode has several distinct
      benefits:
      
      - With interrupts, the DSPI driver in TCFQ mode raises an IRQ after each
        transmitted word. There is more time wasted for the "waitq" event than
        for actual I/O. And the DSPI IRQ count can easily get the largest in
        /proc/interrupts on Freescale boards with attached SPI devices.
      
      - The SPI I/O time is both lower, and more consistently so. Attached to
        some Freescale devices are either PTP switches, or SPI RTCs. For
        reading time off of a SPI slave device, it is important that all SPI
        transfers take a deterministic time to complete.
      
      - In poll mode there is much less time spent by the CPU in hardirq
        context, which helps with the response latency of the system, and at
        the same time there is more control over when interrupts must be
        disabled (to get a precise timestamp measurement): win-win.
      
      On the LS1021A-TSN board, where the SPI device is a SJA1105 PTP switch
      (with a bits_per_word=8 driver), I created a "benchmark" where I read
      its PTP time once per second, for 120 seconds. Each "read PTP time" is a
      12-byte SPI transfer. I then recorded the time before putting the first
      byte in the TX FIFO, and the time after reading the last byte from the
      RX FIFO. That is the transfer delay in nanoseconds.
      
      Interrupt mode:
      
        delay: min 125120 max 168320 mean 150286 std dev 17675.3
      
      Poll mode:
      
        delay: min 69440 max 119040 mean 70312.9 std dev 8065.34
      
      Both the mean latency and the standard deviation are more than 50% lower
      in poll mode than in interrupt mode. This is with an 'ondemand' governor
      on an otherwise idle system - therefore running mostly at 600 MHz out of
      a max of 1200 MHz.
      Signed-off-by: NVladimir Oltean <olteanv@gmail.com>
      Link: https://lore.kernel.org/r/20190905010114.26718-5-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      5d2af8bc
    • V
      spi: spi-fsl-dspi: Implement the PTP system timestamping for TCFQ mode · d6b71dfa
      Vladimir Oltean 提交于
      In this mode, the DSPI controller uses PIO to transfer word by word. In
      comparison, in EOQ mode the 4-word deep FIFO is being used, hence the
      current logic will need some adaptation for which I do not have the
      hardware (Coldfire) to test. It is not clear what is the timing of DMA
      transfers and whether timestamping in the driver brings any overall
      performance increase compared to regular timestamping done in the core.
      
      Short phc2sys summary after 58 minutes of running on LS1021A-TSN with
      interrupts disabled during the critical section:
      
        offset: min -26251 max 16416 mean -21.8672 std dev 863.416
        delay: min 4720 max 57280 mean 5182.49 std dev 1607.19
        lost servo lock 3 times
      
      Summary of the same phc2sys service running for 120 minutes with
      interrupts disabled:
      
        offset: min -378 max 381 mean -0.0083089 std dev 101.495
        delay: min 4720 max 5920 mean 5129.38 std dev 154.899
        lost servo lock 0 times
      
      The minimum delay (pre to post time) in nanoseconds is the same, but the
      maximum delay is quite a bit higher, due to interrupts getting sometimes
      executed and interfering with the measurement. Hence set disable_irqs
      whenever possible (aka when the driver runs in poll mode - otherwise it
      would be a contradiction in terms).
      Signed-off-by: NVladimir Oltean <olteanv@gmail.com>
      Link: https://lore.kernel.org/r/20190905010114.26718-4-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      d6b71dfa
  9. 02 10月, 2019 1 次提交
    • V
      spi: spi-fsl-dspi: Always use the TCFQ devices in poll mode · 3c0f9d8b
      Vladimir Oltean 提交于
      With this patch, the "interrupts" property from the device tree bindings
      is ignored, even if present, if the driver runs in TCFQ mode.
      
      Switching to using the DSPI in poll mode has several distinct
      benefits:
      
      - With interrupts, the DSPI driver in TCFQ mode raises an IRQ after each
        transmitted word. There is more time wasted for the "waitq" event than
        for actual I/O. And the DSPI IRQ count can easily get the largest in
        /proc/interrupts on Freescale boards with attached SPI devices.
      
      - The SPI I/O time is both lower, and more consistently so. Attached to
        some Freescale devices are either PTP switches, or SPI RTCs. For
        reading time off of a SPI slave device, it is important that all SPI
        transfers take a deterministic time to complete.
      
      - In poll mode there is much less time spent by the CPU in hardirq
        context, which helps with the response latency of the system, and at
        the same time there is more control over when interrupts must be
        disabled (to get a precise timestamp measurement, which will come in a
        future patch): win-win.
      
      On the LS1021A-TSN board, where the SPI device is a SJA1105 PTP switch
      (with a bits_per_word=8 driver), I created a "benchmark" where I
      periodically transferred a 12-byte message once per second, for 120
      seconds. I then recorded the time before putting the first byte in the
      TX FIFO, and the time after reading the last byte from the RX FIFO. That
      is the transfer delay in nanoseconds.
      
      Interrupt mode:
      
        delay: min 125120 max 168320 mean 150286 std dev 17675.3
      
      Poll mode:
      
        delay: min 69440 max 119040 mean 70312.9 std dev 8065.34
      
      Both the mean latency and the standard deviation are more than 50% lower
      in poll mode than in interrupt mode, and the 'max' in poll mode is lower
      than the 'min' in interrupt mode. This is with an 'ondemand' governor on
      an otherwise idle system - therefore running mostly at 600 MHz out of a
      max of 1200 MHz.
      Signed-off-by: NVladimir Oltean <olteanv@gmail.com>
      Link: https://lore.kernel.org/r/20191001205216.32115-1-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      3c0f9d8b
  10. 01 10月, 2019 1 次提交
  11. 03 9月, 2019 1 次提交
    • V
      spi: spi-fsl-dspi: Fix race condition in TCFQ/EOQ interrupt · e3273649
      Vladimir Oltean 提交于
      When the driver is working in TCFQ/EOQ mode (i.e. interacts with the SPI
      controller's FIFOs directly) the following sequence of operations
      happens:
      
      - The first byte of the tx buffer gets pushed to the TX FIFO (dspi->len
        gets decremented). This triggers the train of interrupts that handle
        the rest of the bytes.
      
      - The dspi_interrupt handles a TX confirmation event. It reads the newly
        available byte from the RX FIFO, checks the dspi->len exit condition,
        and if there's more to be done, it kicks off the next interrupt in the
        train by writing the next byte to the TX FIFO.
      
      Now the problem is that the wait queue is woken up one byte too early,
      because dspi->len becomes 0 as soon as the byte has been pushed into the
      TX FIFO. Its interrupt has not yet been processed and the RX byte has
      not been put from the FIFO into the buffer.
      
      Depending on the timing of the wait queue wakeup vs the handling of the
      last dspi_interrupt, it can happen that the main SPI message pump thread
      has already returned back into the spi_device driver. When the rx buffer
      is on stack (which it can be, because in this mode, the DSPI doesn't do
      DMA), the last interrupt will perform a memory write into an rx buffer
      that has been freed. This manifests as stack corruption.
      
      The solution is to only wake up the wait queue when dspi_rxtx says so,
      i.e. after it has processed the last TX confirmation interrupt and
      collected the last RX byte.
      
      Fixes: c55be305 ("spi: spi-fsl-dspi: Use poll mode in case the platform IRQ is missing")
      Signed-off-by: NVladimir Oltean <olteanv@gmail.com>
      Link: https://lore.kernel.org/r/20190903105708.32273-1-olteanv@gmail.comSigned-off-by: NMark Brown <broonie@kernel.org>
      e3273649
  12. 23 8月, 2019 5 次提交
  13. 20 8月, 2019 1 次提交