Hi everyone,
I have been trying to implement SPI read by the standard spi_read API, using Freescales mxc-spi.c driver. The spi_write API works fine for me and I confirmed it with the CRO too. But whenever I tried to implement the read operation, the kernel got crashed!.
The error log is given below:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 17 [#1] PREEMPT
Modules linked in:
CPU: 0 Not tainted (2.6.31-207-g7286c01-svn124 #267)
PC is at mxc_spi_buf_tx_u8+0x4/0x14
LR is at spi_put_tx_data+0x24/0x54
pc : [<c01db5c4>] lr : [<c01db6ac>] psr: 80000013
sp : c3869f38 ip : 00000008 fp : c01db6f4
r10: c3870780 r9 : 00000000 r8 : 00380821
r7 : 00000001 r6 : 00000001 r5 : fc0a4000 r4 : c3877cc0
r3 : 00000000 r2 : c3877cc0 r1 : 00000001 r0 : c3877cc0
Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 0005317f Table: 83030000 DAC: 00000017
Process mxc_spi.0 (pid: 134, stack limit = 0xc3868270)
Stack: (0xc3869f38 to 0xc386a000)
9f20: 80000013 c3877cc0
9f40: c3035edc c3870780 00000001 c01dbcb0 c3035edc 00000000 c3035eb0 c3868000
9f60: c3877cc0 c01db450 c38783e0 ffffffff c3868000 c3869fa8 c3868000 c3877cc4
9f80: c38e2d40 c38783e0 00000000 c01db2e4 00000000 c00594ec c02d9a08 00000000
9fa0: c38783e0 c005ce48 c3869fa8 c3869fa8 c0059304 c3869fd4 c3819e60 c38e2d40
9fc0: c0059304 00000000 00000000 c005cd80 00000000 00000000 c3869fd8 c3869fd8
9fe0: 00000000 00000000 00000000 00000000 00000000 c00297bc 00000000 00000000
[<c01db5c4>] (mxc_spi_buf_tx_u8+0x4/0x14) from [<c01db6ac>] (spi_put_tx_data+0x24/0x54)
[<c01db6ac>] (spi_put_tx_data+0x24/0x54) from [<c01dbcb0>] (mxc_spi_transfer+0xd4/0x14c)
[<c01dbcb0>] (mxc_spi_transfer+0xd4/0x14c) from [<c01db450>] (bitbang_work+0x16c/0x2cc)
[<c01db450>] (bitbang_work+0x16c/0x2cc) from [<c00594ec>] (worker_thread+0x1e8/0x2ac)
[<c00594ec>] (worker_thread+0x1e8/0x2ac) from [<c005cd80>] (kthread+0x78/0x80)
[<c005cd80>] (kthread+0x78/0x80) from [<c00297bc>] (kernel_thread_exit+0x0/0x8)
Code: e4c31001 e5803050 e12fff1e e590304c (e4d32001)
---[ end trace e59954a84fe6d7df ]---
This is happening only when I'm performing SPI read.
I refer to the following link "http://forums.freescale.com/t5/i-MX-Microprocessors/i-MX25-SPI-driver-drivers-spi-mxs-spi-c-completely-broken/td-p/60614" and found that some people fixed it already. But I couldn't trace the solution yet. So I hereby request you to provide the patch for fixing this
critical issue. I would also like to know that whether this issue is already solved in the later releases?
Looking forward to your reply...
Ajith P V
Thank you so much Rooney for your effective support.
Rooney said:
The problem is that if you perform a read, the transmit function of the mxc_spi.c is called as well to generate the clock. In case of a read the tx_buf is not initialised, therefore you get a null pointer exception.
You could use the following fix for spi_put_tx_data() in mxc_spi.c
for (i = 0; i < count; i++) {
if(master_drv_data->transfer.tx_buf != NULL)
{
data = master_drv_data->transfer.tx_get(master_drv_data);
__raw_writel(data, base + MXC_CSPITXDATA);
}
else
{
__raw_writel(data, base + 0x00);
}
}
The proposed solution seems to not solve the problem.
The root of the problem is in mxc_spi_pio_transfer invoked by mxc_spi_transfer.
An SPI transfer consists in two steps: a write and a subsequent read, specified in two separated spi_transfer structs (see function spi_write_then_read in spi.c).
The problem is that in the first step only tx_buf in spi_transfer struct exists, and in the second step only rx_buf.
This is taken into account in function mxc_spi_dma_transfer but NOT in mxc_spi_pio_transfer.
So, to summarize, instead of the patch above, add in mxc_spi_pio_transfer function this row after "INIT_COMPLETION(master_drv_data->xfer_done);":
if (!t->tx_buf) master_drv_data->transfer.tx_buf = (void *)master_drv_data->tmp_buf;
Just another broken driver.
Hi Augusto,
Thanks for the reply, it looks promising but it looks like the mxc_spi driver you're using doesn't correlate with the ones in the L2.6.31_09.12.00 or L2.6.35_10.12.01 releases, which is what I (probably incorrectly) thought were the only releases with mx25 fsl drivers. What release are you using?
Sorry, I'm using i.MX53 that's probably different (but buggy as well...)
Hi Augusto,
The 'spi_read bug' in L2.6.31_09.12.00_SDK_SOURCE is fixed in later versions (Freescale suggested me to upgrade the version to new one, once I sent the same query). So i.MX53 might be using a "bug fixed" code...
Thank you for your valuable input by the way...
Thanks for all the input, but on my side I had better results backporting the mainline spi_imx driver.
The problem is that if you perform a read, the transmit function of the mxc_spi.c is called as well to generate the clock. In case of a read the tx_buf is not initialised, therefore you get a null pointer exception.
You could use the following fix for spi_put_tx_data() in mxc_spi.c
for (i = 0; i < count; i++) {
if(master_drv_data->transfer.tx_buf != NULL)
{
data = master_drv_data->transfer.tx_get(master_drv_data);
__raw_writel(data, base + MXC_CSPITXDATA);
}
else
{
__raw_writel(data, base + 0x00);
}
}
Hi Rooney,
Thanks for posting the proposed fix. I had the same problem as Aijith and traced it to the tx.buf being NULL, then was just delighted to find your note and your proposed solution here. I naively dropped your fix into the version of mxc_spi.c that was in the L2.6.31_09.12.00_SDK_SOURCE release but doing so only changed my deref stack dump into a lockup .
Is this same version you were working from, and for that matter is the fix as posted compete or is there something else I need to do?
Thanks,
Glenn
Hi Balaji,
I made a wrapper around the spi_read and fixed the bug. Now it's working without any problem.
Best regards,
Ajith P V
Hi,
Were you able to get it working?
Regards
Balaji.V