Hi,

On Mon, Dec 10, 2012 at 03:19:15PM +0000, Jack Mitchell wrote:
> On 10/12/12 14:59, Felipe Balbi wrote:
> >Hi,
> >
> >On Mon, Dec 10, 2012 at 02:50:16PM +0000, Jack Mitchell wrote:
> >>>On Mon, Dec 10, 2012 at 01:23:09PM +0000, Jack Mitchell wrote:
> >>>>Hi,
> >>>>
> >>>>I am currently having issues with the SPI driver on the beaglebone
> >>>>using the 3.7-rc8 kernel[1]. I have probed the SPI pins and I have
> >>>>found that writing works however reading doesn't. When using DMA the
> >>>>program seems to lock hard and no data is sent on the bus. I am
> >>>>testing the bus using spidev and the spidev_test[2] application,
> >>>>however I first came across spi issues with a custom spi driver which
> >>>>stopped working when I transitioned from 3.2-psp to 3.7-rc8.
> >>>>
> >>>>The current output I am seeing from the spidev_test program is just a
> >>>>series of 0x00 data, which looks to me like no data is getting in at
> >>>>all. The spidev_test program is not using DMA as the buffer size is
> >>>>too low, so I forced the dma on when buffer size is > 1 and the
> >>>>program hangs hard with the system still responding to other
> >>>>commands.I have briged the pins 18 and 21 on the BeagleBone P9
> >>>>header.
> >>>>
> >>>>Has anyone seen issues like this, or if not if someone could please
> >>>>test the latest 3.7-rc8 from [1] and let me know if it works for them
> >>>>and the issue is at my end.
> >>>>
> >>>>To get spidev working with devicetree I applied the patch from [3]
> >>>>and changed the dtb as in the patch pasted below.
> >>>>
> >>>>[1] https://github.com/beagleboard/kernel/tree/3.7
> >>>>[2] http://lxr.linux.no/#linux+v3.6.9/Documentation/spi/spidev_test.c
> >>>>[3] 
> >>>>http://www.mail-archive.com/[email protected]/msg09958.html
> >>>do you have any debugging output from that driver ? It would be cool to
> >>>see if DMA is at least being kicked properly for small transfers.
> >>When I run the spidev program with dma for transfers > 1, the program
> >>hangs and the only output in dmesg is:
> >>
> >>[   12.613952] libphy: 4a101000.mdio:00 - Link is Up - 100/Full <----
> >>Last line from initial log in [2]
> >>[   47.669202] spidev spi1.0: setup: speed 24000000, sample leading
> >>edge, clk normal
> >>[   47.669246] spidev spi1.0: setup mode 0, 8 bits/w, 24000000 Hz max --> 0
> >>[   47.669260] spidev spi1.0: spi mode 00
> >>[   47.669283] spidev spi1.0: setup: speed 24000000, sample leading
> >>edge, clk normal
> >>[   47.669300] spidev spi1.0: setup mode 0, 16 bits/w, 24000000 Hz max --> 0
> >>[   47.669312] spidev spi1.0: 16 bits per word
> >>[   47.669330] spidev spi1.0: setup: speed 24000000, sample leading
> >>edge, clk normal
> >>[   47.669347] spidev spi1.0: setup mode 0, 16 bits/w, 24000000 Hz max --> 0
> >>[   47.669358] spidev spi1.0: 24000000 Hz (max)
> >>[   47.673811] spidev spi1.0: setup: speed 24000000, sample leading
> >>edge, clk normal
> >>
> >>The initial dmesg statup log is at [2].
> >can you apply the debugging patch below to spi driver and show me the
> >output again ?
> >
> >Note that I'm allowing DMA for as small as 1-byte transfers (as you
> >needed) and I'm also disabling DMA Request line before calling
> >complete() as I think the current way could race, but likely wouldn't
> >cause issues. Anyway, please show me the output.
> >
> >diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
> >index 3542fdc..d2b1af2 100644
> >--- a/drivers/spi/spi-omap2-mcspi.c
> >+++ b/drivers/spi/spi-omap2-mcspi.c
> >@@ -108,7 +108,7 @@ struct omap2_mcspi_dma {
> >  /* use PIO for small transfers, avoiding DMA setup/teardown overhead and
> >   * cache operations; better heuristics consider wordsize and bitrate.
> >   */
> >-#define DMA_MIN_BYTES                       160
> >+#define DMA_MIN_BYTES                       1
> >  /*
> >@@ -298,10 +298,11 @@ static void omap2_mcspi_rx_callback(void *data)
> >     struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
> >     struct omap2_mcspi_dma *mcspi_dma = 
> > &mcspi->dma_channels[spi->chip_select];
> >-    complete(&mcspi_dma->dma_rx_completion);
> >-
> >     /* We must disable the DMA RX request */
> >+    dev_info(&spi->dev, "Disabling RX Request Line\n");
> >     omap2_mcspi_set_dma_req(spi, 1, 0);
> >+
> >+    complete(&mcspi_dma->dma_rx_completion);
> >  }
> >  static void omap2_mcspi_tx_callback(void *data)
> >@@ -310,10 +311,11 @@ static void omap2_mcspi_tx_callback(void *data)
> >     struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
> >     struct omap2_mcspi_dma *mcspi_dma = 
> > &mcspi->dma_channels[spi->chip_select];
> >-    complete(&mcspi_dma->dma_tx_completion);
> >-
> >     /* We must disable the DMA TX request */
> >+    dev_info(&spi->dev, "Disabling TX Request Line\n");
> >     omap2_mcspi_set_dma_req(spi, 0, 0);
> >+
> >+    complete(&mcspi_dma->dma_tx_completion);
> >  }
> >  static void omap2_mcspi_tx_dma(struct spi_device *spi,
> >@@ -328,6 +330,7 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
> >     void __iomem            *chstat_reg;
> >     struct omap2_mcspi_cs   *cs = spi->controller_state;
> >+    dev_info(&spi->dev, "kicking TX DMA\n");
> >     mcspi = spi_master_get_devdata(spi->master);
> >     mcspi_dma = &mcspi->dma_channels[spi->chip_select];
> >     count = xfer->len;
> >@@ -359,7 +362,9 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
> >     dma_async_issue_pending(mcspi_dma->dma_tx);
> >     omap2_mcspi_set_dma_req(spi, 0, 1);
> >+    dev_info(&spi->dev, "Waiting for TX Completion\n");
> >     wait_for_completion(&mcspi_dma->dma_tx_completion);
> >+    dev_info(&spi->dev, "TX Completed\n");
> >     dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
> >                      DMA_TO_DEVICE);
> >@@ -392,6 +397,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct 
> >spi_transfer *xfer,
> >     word_len = cs->word_len;
> >     l = mcspi_cached_chconf0(spi);
> >+    dev_info(&spi->dev, "kicking RX DMA\n");
> >     if (word_len <= 8)
> >             element_count = count;
> >     else if (word_len <= 16)
> >@@ -428,7 +434,9 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct 
> >spi_transfer *xfer,
> >     dma_async_issue_pending(mcspi_dma->dma_rx);
> >     omap2_mcspi_set_dma_req(spi, 1, 1);
> >+    dev_info(&spi->dev, "Waiting for RX Completion\n");
> >     wait_for_completion(&mcspi_dma->dma_rx_completion);
> >+    dev_info(&spi->dev, "RX Completed\n");
> >     dma_unmap_single(mcspi->dev, xfer->rx_dma, count,
> >                      DMA_FROM_DEVICE);
> >     omap2_mcspi_set_enable(spi, 0);
> >
> >>>It would also be nice to have a clear picture of what "custom spi
> >>>driver" you're talking about.
> >>The custom SPI driver is for connecting and reading registers from an
> >>in house FPGA design and can be found at [1]. It's fairly rudimentary
> >>and also in the development stages, I'm very new to Linux kernel
> >>programming so please take that into account :)
> >no problem ;-)
> >
> >>However it did work flawlessly with 3.2-psp.
> >yeah, it could be some regression introduced somewhere, or just a bugfix
> >which was done on 3.2-psp and was missed upstream... annoying when those
> >happen :-p
> >
> 
> Your patch didn't apply cleanly but I hacked it in and got the following:
> 
> [   40.434566] spidev spi1.0: setup: speed 24000000, sample leading
> edge, clk normal
> [   40.434609] spidev spi1.0: setup mode 0, 8 bits/w, 24000000 Hz max --> 0
> [   40.434622] spidev spi1.0: spi mode 00
> [   40.434645] spidev spi1.0: setup: speed 24000000, sample leading
> edge, clk normal
> [   40.434661] spidev spi1.0: setup mode 0, 16 bits/w, 24000000 Hz max --> 0
> [   40.434673] spidev spi1.0: 16 bits per word
> [   40.434692] spidev spi1.0: setup: speed 24000000, sample leading
> edge, clk normal
> [   40.434708] spidev spi1.0: setup mode 0, 16 bits/w, 24000000 Hz max --> 0
> [   40.434720] spidev spi1.0: 24000000 Hz (max)
> [   40.439300] spidev spi1.0: setup: speed 24000000, sample leading
> edge, clk normal
> [   40.439397] spidev spi1.0: kicking TX DMA
> [   40.443797] spidev spi1.0: Waiting for TX Completion

so TX dma never completes... perhaps all you need is Shubhro's commit
reordering TX and RX calls ??

commit e47a682ace0cd56eb8e09b806c2b0f034b491520
Author: Shubhrajyoti D <[email protected]>
Date:   Tue Nov 6 14:30:19 2012 +0530

    spi: omap2-mcspi: Reorder the wait_for_completion for tx
    
    The commit  d7b4394e[Cleanup the omap2_mcspi_txrx_dma function]
    changed the wait_for_completion order. Move the wait so that the
    rx doesnot wait for the tx to complete.
    
    Reported-and-tested-by: Sørensen, Stefan <[email protected]>
    Signed-off-by: Shubhrajyoti D <[email protected]>
    Signed-off-by: Mark Brown <[email protected]>

diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 3542fdc..b1a651e 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -323,18 +323,13 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
        struct omap2_mcspi      *mcspi;
        struct omap2_mcspi_dma  *mcspi_dma;
        unsigned int            count;
-       u8                      * rx;
        const u8                * tx;
-       void __iomem            *chstat_reg;
-       struct omap2_mcspi_cs   *cs = spi->controller_state;
 
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
        count = xfer->len;
 
-       rx = xfer->rx_buf;
        tx = xfer->tx_buf;
-       chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
 
        if (mcspi_dma->dma_tx) {
                struct dma_async_tx_descriptor *tx;
@@ -359,19 +354,6 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
        dma_async_issue_pending(mcspi_dma->dma_tx);
        omap2_mcspi_set_dma_req(spi, 0, 1);
 
-       wait_for_completion(&mcspi_dma->dma_tx_completion);
-       dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
-                        DMA_TO_DEVICE);
-
-       /* for TX_ONLY mode, be sure all words have shifted out */
-       if (rx == NULL) {
-               if (mcspi_wait_for_reg_bit(chstat_reg,
-                                       OMAP2_MCSPI_CHSTAT_TXS) < 0)
-                       dev_err(&spi->dev, "TXS timed out\n");
-               else if (mcspi_wait_for_reg_bit(chstat_reg,
-                                       OMAP2_MCSPI_CHSTAT_EOT) < 0)
-                       dev_err(&spi->dev, "EOT timed out\n");
-       }
 }
 
 static unsigned
@@ -492,6 +474,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
spi_transfer *xfer)
        struct dma_slave_config cfg;
        enum dma_slave_buswidth width;
        unsigned es;
+       void __iomem            *chstat_reg;
 
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -526,8 +509,24 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct 
spi_transfer *xfer)
                omap2_mcspi_tx_dma(spi, xfer, cfg);
 
        if (rx != NULL)
-               return omap2_mcspi_rx_dma(spi, xfer, cfg, es);
-
+               count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
+
+       if (tx != NULL) {
+               chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+               wait_for_completion(&mcspi_dma->dma_tx_completion);
+               dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
+                                DMA_TO_DEVICE);
+
+               /* for TX_ONLY mode, be sure all words have shifted out */
+               if (rx == NULL) {
+                       if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_TXS) < 0)
+                               dev_err(&spi->dev, "TXS timed out\n");
+                       else if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_EOT) < 0)
+                               dev_err(&spi->dev, "EOT timed out\n");
+               }
+       }
        return count;
 }
 

Shubhro, what do you think ? could this be the case ?

-- 
balbi

Attachment: signature.asc
Description: Digital signature

Reply via email to