.. | .. |
---|
69 | 69 | module_param(qcaspi_pluggable, int, 0); |
---|
70 | 70 | MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no)."); |
---|
71 | 71 | |
---|
| 72 | +#define QCASPI_WRITE_VERIFY_MIN 0 |
---|
| 73 | +#define QCASPI_WRITE_VERIFY_MAX 3 |
---|
| 74 | +static int wr_verify = QCASPI_WRITE_VERIFY_MIN; |
---|
| 75 | +module_param(wr_verify, int, 0); |
---|
| 76 | +MODULE_PARM_DESC(wr_verify, "SPI register write verify trails. Use 0-3."); |
---|
| 77 | + |
---|
72 | 78 | #define QCASPI_TX_TIMEOUT (1 * HZ) |
---|
73 | 79 | #define QCASPI_QCA7K_REBOOT_TIME_MS 1000 |
---|
74 | 80 | |
---|
.. | .. |
---|
77 | 83 | { |
---|
78 | 84 | *intr_cause = 0; |
---|
79 | 85 | |
---|
80 | | - qcaspi_write_register(qca, SPI_REG_INTR_ENABLE, 0); |
---|
| 86 | + qcaspi_write_register(qca, SPI_REG_INTR_ENABLE, 0, wr_verify); |
---|
81 | 87 | qcaspi_read_register(qca, SPI_REG_INTR_CAUSE, intr_cause); |
---|
82 | 88 | netdev_dbg(qca->net_dev, "interrupts: 0x%04x\n", *intr_cause); |
---|
83 | 89 | } |
---|
.. | .. |
---|
90 | 96 | SPI_INT_RDBUF_ERR | |
---|
91 | 97 | SPI_INT_WRBUF_ERR); |
---|
92 | 98 | |
---|
93 | | - qcaspi_write_register(qca, SPI_REG_INTR_CAUSE, intr_cause); |
---|
94 | | - qcaspi_write_register(qca, SPI_REG_INTR_ENABLE, intr_enable); |
---|
| 99 | + qcaspi_write_register(qca, SPI_REG_INTR_CAUSE, intr_cause, 0); |
---|
| 100 | + qcaspi_write_register(qca, SPI_REG_INTR_ENABLE, intr_enable, wr_verify); |
---|
95 | 101 | netdev_dbg(qca->net_dev, "acking int: 0x%04x\n", intr_cause); |
---|
96 | 102 | } |
---|
97 | 103 | |
---|
.. | .. |
---|
239 | 245 | |
---|
240 | 246 | len = skb->len; |
---|
241 | 247 | |
---|
242 | | - qcaspi_write_register(qca, SPI_REG_BFR_SIZE, len); |
---|
| 248 | + qcaspi_write_register(qca, SPI_REG_BFR_SIZE, len, wr_verify); |
---|
243 | 249 | if (qca->legacy_mode) |
---|
244 | 250 | qcaspi_tx_cmd(qca, QCA7K_SPI_WRITE | QCA7K_SPI_EXTERNAL); |
---|
245 | 251 | |
---|
.. | .. |
---|
282 | 288 | return 0; |
---|
283 | 289 | |
---|
284 | 290 | qcaspi_read_register(qca, SPI_REG_WRBUF_SPC_AVA, &available); |
---|
| 291 | + |
---|
| 292 | + if (available > QCASPI_HW_BUF_LEN) { |
---|
| 293 | + /* This could only happen by interferences on the SPI line. |
---|
| 294 | + * So retry later ... |
---|
| 295 | + */ |
---|
| 296 | + qca->stats.buf_avail_err++; |
---|
| 297 | + return -1; |
---|
| 298 | + } |
---|
285 | 299 | |
---|
286 | 300 | while (qca->txr.skb[qca->txr.head]) { |
---|
287 | 301 | pkt_len = qca->txr.skb[qca->txr.head]->len + QCASPI_HW_PKT_LEN; |
---|
.. | .. |
---|
345 | 359 | |
---|
346 | 360 | /* Read the packet size. */ |
---|
347 | 361 | qcaspi_read_register(qca, SPI_REG_RDBUF_BYTE_AVA, &available); |
---|
| 362 | + |
---|
348 | 363 | netdev_dbg(net_dev, "qcaspi_receive: SPI_REG_RDBUF_BYTE_AVA: Value: %08x\n", |
---|
349 | 364 | available); |
---|
350 | 365 | |
---|
351 | | - if (available == 0) { |
---|
| 366 | + if (available > QCASPI_HW_BUF_LEN + QCASPI_HW_PKT_LEN) { |
---|
| 367 | + /* This could only happen by interferences on the SPI line. |
---|
| 368 | + * So retry later ... |
---|
| 369 | + */ |
---|
| 370 | + qca->stats.buf_avail_err++; |
---|
| 371 | + return -1; |
---|
| 372 | + } else if (available == 0) { |
---|
352 | 373 | netdev_dbg(net_dev, "qcaspi_receive called without any data being available!\n"); |
---|
353 | 374 | return -1; |
---|
354 | 375 | } |
---|
355 | 376 | |
---|
356 | | - qcaspi_write_register(qca, SPI_REG_BFR_SIZE, available); |
---|
| 377 | + qcaspi_write_register(qca, SPI_REG_BFR_SIZE, available, wr_verify); |
---|
357 | 378 | |
---|
358 | 379 | if (qca->legacy_mode) |
---|
359 | 380 | qcaspi_tx_cmd(qca, QCA7K_SPI_READ | QCA7K_SPI_EXTERNAL); |
---|
.. | .. |
---|
523 | 544 | netdev_dbg(qca->net_dev, "sync: resetting device.\n"); |
---|
524 | 545 | qcaspi_read_register(qca, SPI_REG_SPI_CONFIG, &spi_config); |
---|
525 | 546 | spi_config |= QCASPI_SLAVE_RESET_BIT; |
---|
526 | | - qcaspi_write_register(qca, SPI_REG_SPI_CONFIG, spi_config); |
---|
| 547 | + qcaspi_write_register(qca, SPI_REG_SPI_CONFIG, spi_config, 0); |
---|
527 | 548 | |
---|
528 | 549 | qca->sync = QCASPI_SYNC_RESET; |
---|
529 | 550 | qca->stats.trig_reset++; |
---|
.. | .. |
---|
553 | 574 | while (!kthread_should_stop()) { |
---|
554 | 575 | set_current_state(TASK_INTERRUPTIBLE); |
---|
555 | 576 | if ((qca->intr_req == qca->intr_svc) && |
---|
556 | | - (qca->txr.skb[qca->txr.head] == NULL) && |
---|
557 | | - (qca->sync == QCASPI_SYNC_READY)) |
---|
| 577 | + !qca->txr.skb[qca->txr.head]) |
---|
558 | 578 | schedule(); |
---|
559 | 579 | |
---|
560 | 580 | set_current_state(TASK_RUNNING); |
---|
.. | .. |
---|
683 | 703 | |
---|
684 | 704 | netif_stop_queue(dev); |
---|
685 | 705 | |
---|
686 | | - qcaspi_write_register(qca, SPI_REG_INTR_ENABLE, 0); |
---|
| 706 | + qcaspi_write_register(qca, SPI_REG_INTR_ENABLE, 0, wr_verify); |
---|
687 | 707 | free_irq(qca->spi_dev->irq, qca); |
---|
688 | 708 | |
---|
689 | 709 | kthread_stop(qca->spi_thread); |
---|
.. | .. |
---|
764 | 784 | } |
---|
765 | 785 | |
---|
766 | 786 | static void |
---|
767 | | -qcaspi_netdev_tx_timeout(struct net_device *dev) |
---|
| 787 | +qcaspi_netdev_tx_timeout(struct net_device *dev, unsigned int txqueue) |
---|
768 | 788 | { |
---|
769 | 789 | struct qcaspi *qca = netdev_priv(dev); |
---|
770 | 790 | |
---|
.. | .. |
---|
815 | 835 | |
---|
816 | 836 | kfree(qca->rx_buffer); |
---|
817 | 837 | qca->buffer_size = 0; |
---|
818 | | - if (qca->rx_skb) |
---|
819 | | - dev_kfree_skb(qca->rx_skb); |
---|
| 838 | + dev_kfree_skb(qca->rx_skb); |
---|
820 | 839 | } |
---|
821 | 840 | |
---|
822 | 841 | static const struct net_device_ops qcaspi_netdev_ops = { |
---|
.. | .. |
---|
903 | 922 | return -EINVAL; |
---|
904 | 923 | } |
---|
905 | 924 | |
---|
| 925 | + if (wr_verify < QCASPI_WRITE_VERIFY_MIN || |
---|
| 926 | + wr_verify > QCASPI_WRITE_VERIFY_MAX) { |
---|
| 927 | + dev_err(&spi->dev, "Invalid write verify: %d\n", |
---|
| 928 | + wr_verify); |
---|
| 929 | + return -EINVAL; |
---|
| 930 | + } |
---|
| 931 | + |
---|
906 | 932 | dev_info(&spi->dev, "ver=%s, clkspeed=%d, burst_len=%d, pluggable=%d\n", |
---|
907 | 933 | QCASPI_DRV_VERSION, |
---|
908 | 934 | qcaspi_clkspeed, |
---|
.. | .. |
---|
937 | 963 | |
---|
938 | 964 | mac = of_get_mac_address(spi->dev.of_node); |
---|
939 | 965 | |
---|
940 | | - if (mac) |
---|
| 966 | + if (!IS_ERR(mac)) |
---|
941 | 967 | ether_addr_copy(qca->net_dev->dev_addr, mac); |
---|
942 | 968 | |
---|
943 | 969 | if (!is_valid_ether_addr(qca->net_dev->dev_addr)) { |
---|