| .. | .. |
|---|
| 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)) { |
|---|