]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: qca_spi: Add available buffer space verification
authorStefan Wahren <stefan.wahren@i2se.com>
Thu, 8 Nov 2018 13:38:21 +0000 (14:38 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 Nov 2018 03:41:01 +0000 (19:41 -0800)
Interferences on the SPI line could distort the response of
available buffer space. So at least we should check that the
response doesn't exceed the maximum available buffer space.
In error case increase a new error counter and retry it later.
This behavior avoids buffer errors in the QCA7000, which
results in an unnecessary chip reset including packet loss.

Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qualcomm/qca_debug.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/qualcomm/qca_spi.h

index a9f1bc013364763a818a1626184adc87fa38830d..1450f386bc657557960b0e785cbc06a29a8e873a 100644 (file)
@@ -61,6 +61,7 @@ static const char qcaspi_gstrings_stats[][ETH_GSTRING_LEN] = {
        "Transmit ring full",
        "SPI errors",
        "Write verify errors",
+       "Buffer available errors",
 };
 
 #ifdef CONFIG_DEBUG_FS
index d5310504f4364349bf235f8d8f82eb7a14348a70..97f92953bdb9c071deaf705a607589a12d064a53 100644 (file)
@@ -289,6 +289,14 @@ qcaspi_transmit(struct qcaspi *qca)
 
        qcaspi_read_register(qca, SPI_REG_WRBUF_SPC_AVA, &available);
 
+       if (available > QCASPI_HW_BUF_LEN) {
+               /* This could only happen by interferences on the SPI line.
+                * So retry later ...
+                */
+               qca->stats.buf_avail_err++;
+               return -1;
+       }
+
        while (qca->txr.skb[qca->txr.head]) {
                pkt_len = qca->txr.skb[qca->txr.head]->len + QCASPI_HW_PKT_LEN;
 
@@ -355,7 +363,13 @@ qcaspi_receive(struct qcaspi *qca)
        netdev_dbg(net_dev, "qcaspi_receive: SPI_REG_RDBUF_BYTE_AVA: Value: %08x\n",
                   available);
 
-       if (available == 0) {
+       if (available > QCASPI_HW_BUF_LEN) {
+               /* This could only happen by interferences on the SPI line.
+                * So retry later ...
+                */
+               qca->stats.buf_avail_err++;
+               return -1;
+       } else if (available == 0) {
                netdev_dbg(net_dev, "qcaspi_receive called without any data being available!\n");
                return -1;
        }
index 2d2c4972649245e8ffb24abadaaf107cb9a15bd3..eb9af45fcc5e9a903e65bc537cc46baa51392058 100644 (file)
@@ -74,6 +74,7 @@ struct qcaspi_stats {
        u64 ring_full;
        u64 spi_err;
        u64 write_verify_failed;
+       u64 buf_avail_err;
 };
 
 struct qcaspi {