kernel: rename CONFIG_TRACE_ENUM_MAP_FILE to CONFIG_TRACE_EVAL_MAP_FILE
[oweals/openwrt.git] / target / linux / ipq806x / patches-4.9 / 0014-spi-qup-Fix-sg-nents-calculation.patch
1 From f5913e137c3dac4972ac0ddd5f248924d02d3dcb Mon Sep 17 00:00:00 2001
2 From: Varadarajan Narayanan <varada@codeaurora.org>
3 Date: Wed, 25 May 2016 13:40:03 +0530
4 Subject: [PATCH 14/69] spi: qup: Fix sg nents calculation
5
6 lib/scatterlist.c:sg_nents_for_len() returns the number of SG
7 entries that total up to greater than or equal to the given
8 length. However, the spi-qup driver assumed that the returned
9 nents is for a total less than or equal to the given length. The
10 spi-qup driver requests nents for SPI_MAX_XFER, however the API
11 returns nents for SPI_MAX_XFER+delta (actually SZ_64K).
12
13 Based on this, spi_qup_do_dma() calculates n_words and programs
14 that into  QUP_MX_{IN|OUT}PUT_CNT register. The calculated
15 n_words value is more than the maximum value that can fit in the
16 the 16-bit COUNT field of the QUP_MX_{IN|OUT}PUT_CNT register.
17 And, the field gets programmed to zero. Since the COUNT field is
18 zero, the i/o doesn't start eventually resulting in the i/o
19 timing out.
20
21 Signed-off-by: Varadarajan Narayanan <varada@codeaurora.org>
22 ---
23  drivers/spi/spi-qup.c | 38 ++++++++++++++++++++++++++++++++++++--
24  1 file changed, 36 insertions(+), 2 deletions(-)
25
26 --- a/drivers/spi/spi-qup.c
27 +++ b/drivers/spi/spi-qup.c
28 @@ -581,6 +581,38 @@ static unsigned int spi_qup_sgl_get_size
29         return length;
30  }
31  
32 +/**
33 + * spi_qup_sg_nents_for_len - return total count of entries in scatterlist
34 + *                           needed to satisfy the supplied length
35 + * @sg:                The scatterlist
36 + * @len:       The total required length
37 + *
38 + * Description:
39 + * Determines the number of entries in sg that sum upto a maximum of
40 + * the supplied length, taking into acount chaining as well
41 + *
42 + * Returns:
43 + *   the number of sg entries needed, negative error on failure
44 + *
45 + **/
46 +int spi_qup_sg_nents_for_len(struct scatterlist *sg, u64 len)
47 +{
48 +       int nents;
49 +       u64 total;
50 +
51 +       if (!len)
52 +               return 0;
53 +
54 +       for (nents = 0, total = 0; sg; sg = sg_next(sg)) {
55 +               nents++;
56 +               total += sg_dma_len(sg);
57 +               if (total > len)
58 +                       return (nents - 1);
59 +       }
60 +
61 +       return -EINVAL;
62 +}
63 +
64  static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer,
65  unsigned long timeout)
66  {
67 @@ -597,7 +629,8 @@ unsigned long timeout)
68                 int rx_nents = 0, tx_nents = 0;
69  
70                 if (rx_sgl) {
71 -                       rx_nents = sg_nents_for_len(rx_sgl, SPI_MAX_XFER);
72 +                       rx_nents = spi_qup_sg_nents_for_len(rx_sgl,
73 +                                                               SPI_MAX_XFER);
74                         if (rx_nents < 0)
75                                 rx_nents = sg_nents(rx_sgl);
76  
77 @@ -606,7 +639,8 @@ unsigned long timeout)
78                 }
79  
80                 if (tx_sgl) {
81 -                       tx_nents = sg_nents_for_len(tx_sgl, SPI_MAX_XFER);
82 +                       tx_nents = spi_qup_sg_nents_for_len(tx_sgl,
83 +                                                               SPI_MAX_XFER);
84                         if (tx_nents < 0)
85                                 tx_nents = sg_nents(tx_sgl);
86