Skip to content

Commit f3e03e2

Browse files
Tomoya MORINAGAglikely
authored andcommitted
spi-topcliff-pch: Fix overrun issue
We found that adding load, Rx data sometimes drops.(with DMA transfer mode) The cause is that before starting Rx-DMA processing, Tx-DMA processing starts. This causes FIFO overrun occurs. This patch fixes the issue by modifying FIFO tx-threshold and DMA descriptor size like below. Current this patch Rx-descriptor 4Byte+12Byte*341 --> 12Byte*340-4Byte-12Byte Rx-threshold (Not modified) Tx-descriptor 4Byte+12Byte*341 --> 16Byte-12Byte*340 Rx-threshold 12Byte --> 2Byte Signed-off-by: Tomoya MORINAGA <[email protected]> Signed-off-by: Grant Likely <[email protected]>
1 parent 25e803f commit f3e03e2

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

drivers/spi/spi-topcliff-pch.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
#define PCH_RX_THOLD 7
5151
#define PCH_RX_THOLD_MAX 15
5252

53+
#define PCH_TX_THOLD 2
54+
5355
#define PCH_MAX_BAUDRATE 5000000
5456
#define PCH_MAX_FIFO_DEPTH 16
5557

@@ -1040,8 +1042,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
10401042
/* set receive fifo threshold and transmit fifo threshold */
10411043
pch_spi_setclr_reg(data->master, PCH_SPCR,
10421044
((size - 1) << SPCR_RFIC_FIELD) |
1043-
((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) <<
1044-
SPCR_TFIC_FIELD),
1045+
(PCH_TX_THOLD << SPCR_TFIC_FIELD),
10451046
MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS);
10461047

10471048
spin_unlock_irqrestore(&data->lock, flags);
@@ -1052,13 +1053,20 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
10521053
/* offset, length setting */
10531054
sg = dma->sg_rx_p;
10541055
for (i = 0; i < num; i++, sg++) {
1055-
if (i == 0) {
1056-
sg->offset = 0;
1056+
if (i == (num - 2)) {
1057+
sg->offset = size * i;
1058+
sg->offset = sg->offset * (*bpw / 8);
10571059
sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem,
10581060
sg->offset);
10591061
sg_dma_len(sg) = rem;
1062+
} else if (i == (num - 1)) {
1063+
sg->offset = size * (i - 1) + rem;
1064+
sg->offset = sg->offset * (*bpw / 8);
1065+
sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
1066+
sg->offset);
1067+
sg_dma_len(sg) = size;
10601068
} else {
1061-
sg->offset = rem + size * (i - 1);
1069+
sg->offset = size * i;
10621070
sg->offset = sg->offset * (*bpw / 8);
10631071
sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
10641072
sg->offset);
@@ -1082,6 +1090,16 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
10821090
dma->desc_rx = desc_rx;
10831091

10841092
/* TX */
1093+
if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
1094+
num = data->bpw_len / PCH_DMA_TRANS_SIZE;
1095+
size = PCH_DMA_TRANS_SIZE;
1096+
rem = 16;
1097+
} else {
1098+
num = 1;
1099+
size = data->bpw_len;
1100+
rem = data->bpw_len;
1101+
}
1102+
10851103
dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
10861104
sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
10871105
/* offset, length setting */

0 commit comments

Comments
 (0)