diff options
Diffstat (limited to 'drivers/net/ethernet/qualcomm/qca_spi.c')
-rw-r--r-- | drivers/net/ethernet/qualcomm/qca_spi.c | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 5799ecc88a87..38a779f4b866 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -35,6 +35,9 @@ #define MAX_DMA_BURST_LEN 5000 +#define SPI_INTR 0 +#define SPI_RESET 1 + /* Modules parameters */ #define QCASPI_CLK_SPEED_MIN 1000000 #define QCASPI_CLK_SPEED_MAX 16000000 @@ -51,7 +54,7 @@ MODULE_PARM_DESC(qcaspi_burst_len, "Number of data bytes per burst. Use 1-5000." #define QCASPI_PLUGGABLE_MIN 0 #define QCASPI_PLUGGABLE_MAX 1 -static int qcaspi_pluggable = QCASPI_PLUGGABLE_MIN; +static int qcaspi_pluggable = QCASPI_PLUGGABLE_MAX; module_param(qcaspi_pluggable, int, 0); MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no)."); @@ -493,7 +496,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event) if (qca->sync == QCASPI_SYNC_READY) qca->stats.bad_signature++; - qca->sync = QCASPI_SYNC_UNKNOWN; + set_bit(SPI_RESET, &qca->flags); netdev_dbg(qca->net_dev, "sync: got CPU on, but signature was invalid, restart\n"); return; } else { @@ -503,12 +506,17 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event) if (wrbuf_space != QCASPI_HW_BUF_LEN) { netdev_dbg(qca->net_dev, "sync: got CPU on, but wrbuf not empty. reset!\n"); qca->sync = QCASPI_SYNC_UNKNOWN; + qca->stats.buf_avail_err++; } else { netdev_dbg(qca->net_dev, "sync: got CPU on, now in sync\n"); qca->sync = QCASPI_SYNC_READY; return; } } + } else { + /* Handle reset only on QCASPI_EVENT_UPDATE */ + if (test_and_clear_bit(SPI_RESET, &qca->flags)) + qca->sync = QCASPI_SYNC_UNKNOWN; } switch (qca->sync) { @@ -519,7 +527,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event) qcaspi_read_register(qca, SPI_REG_SIGNATURE, &signature); if (signature != QCASPI_GOOD_SIGNATURE) { - qca->sync = QCASPI_SYNC_UNKNOWN; + set_bit(SPI_RESET, &qca->flags); qca->stats.bad_signature++; netdev_dbg(qca->net_dev, "sync: bad signature, restart\n"); /* don't reset right away */ @@ -550,7 +558,7 @@ qcaspi_qca7k_sync(struct qcaspi *qca, int event) qca->reset_count); if (qca->reset_count >= QCASPI_RESET_TIMEOUT) { /* reset did not seem to take place, try again */ - qca->sync = QCASPI_SYNC_UNKNOWN; + set_bit(SPI_RESET, &qca->flags); qca->stats.reset_timeout++; netdev_dbg(qca->net_dev, "sync: reset timeout, restarting process.\n"); } @@ -579,14 +587,14 @@ qcaspi_spi_thread(void *data) continue; } - if ((qca->intr_req == qca->intr_svc) && + if (!qca->flags && !qca->txr.skb[qca->txr.head]) schedule(); set_current_state(TASK_RUNNING); - netdev_dbg(qca->net_dev, "have work to do. int: %d, tx_skb: %p\n", - qca->intr_req - qca->intr_svc, + netdev_dbg(qca->net_dev, "have work to do. int: %lu, tx_skb: %p\n", + qca->flags, qca->txr.skb[qca->txr.head]); qcaspi_qca7k_sync(qca, QCASPI_EVENT_UPDATE); @@ -600,8 +608,7 @@ qcaspi_spi_thread(void *data) msleep(QCASPI_QCA7K_REBOOT_TIME_MS); } - if (qca->intr_svc != qca->intr_req) { - qca->intr_svc = qca->intr_req; + if (test_and_clear_bit(SPI_INTR, &qca->flags)) { start_spi_intr_handling(qca, &intr_cause); if (intr_cause & SPI_INT_CPU_ON) { @@ -626,7 +633,7 @@ qcaspi_spi_thread(void *data) /* restart sync */ netdev_dbg(qca->net_dev, "===> rdbuf error!\n"); qca->stats.read_buf_err++; - qca->sync = QCASPI_SYNC_UNKNOWN; + set_bit(SPI_RESET, &qca->flags); continue; } @@ -634,7 +641,7 @@ qcaspi_spi_thread(void *data) /* restart sync */ netdev_dbg(qca->net_dev, "===> wrbuf error!\n"); qca->stats.write_buf_err++; - qca->sync = QCASPI_SYNC_UNKNOWN; + set_bit(SPI_RESET, &qca->flags); continue; } @@ -663,7 +670,7 @@ qcaspi_intr_handler(int irq, void *data) { struct qcaspi *qca = data; - qca->intr_req++; + set_bit(SPI_INTR, &qca->flags); if (qca->spi_thread) wake_up_process(qca->spi_thread); @@ -679,8 +686,7 @@ qcaspi_netdev_open(struct net_device *dev) if (!qca) return -EINVAL; - qca->intr_req = 1; - qca->intr_svc = 0; + set_bit(SPI_INTR, &qca->flags); qca->sync = QCASPI_SYNC_UNKNOWN; qcafrm_fsm_init_spi(&qca->frm_handle); @@ -799,7 +805,7 @@ qcaspi_netdev_tx_timeout(struct net_device *dev, unsigned int txqueue) jiffies, jiffies - dev_trans_start(dev)); qca->net_dev->stats.tx_errors++; /* Trigger tx queue flush and QCA7000 reset */ - qca->sync = QCASPI_SYNC_UNKNOWN; + set_bit(SPI_RESET, &qca->flags); if (qca->spi_thread) wake_up_process(qca->spi_thread); @@ -812,7 +818,6 @@ qcaspi_netdev_init(struct net_device *dev) dev->mtu = QCAFRM_MAX_MTU; dev->type = ARPHRD_ETHER; - qca->clkspeed = qcaspi_clkspeed; qca->burst_len = qcaspi_burst_len; qca->spi_thread = NULL; qca->buffer_size = (QCAFRM_MAX_MTU + VLAN_ETH_HLEN + QCAFRM_HEADER_LEN + @@ -903,17 +908,15 @@ qca_spi_probe(struct spi_device *spi) legacy_mode = of_property_read_bool(spi->dev.of_node, "qca,legacy-mode"); - if (qcaspi_clkspeed == 0) { - if (spi->max_speed_hz) - qcaspi_clkspeed = spi->max_speed_hz; - else - qcaspi_clkspeed = QCASPI_CLK_SPEED; - } + if (qcaspi_clkspeed) + spi->max_speed_hz = qcaspi_clkspeed; + else if (!spi->max_speed_hz) + spi->max_speed_hz = QCASPI_CLK_SPEED; - if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) || - (qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) { - dev_err(&spi->dev, "Invalid clkspeed: %d\n", - qcaspi_clkspeed); + if (spi->max_speed_hz < QCASPI_CLK_SPEED_MIN || + spi->max_speed_hz > QCASPI_CLK_SPEED_MAX) { + dev_err(&spi->dev, "Invalid clkspeed: %u\n", + spi->max_speed_hz); return -EINVAL; } @@ -938,14 +941,13 @@ qca_spi_probe(struct spi_device *spi) return -EINVAL; } - dev_info(&spi->dev, "ver=%s, clkspeed=%d, burst_len=%d, pluggable=%d\n", + dev_info(&spi->dev, "ver=%s, clkspeed=%u, burst_len=%d, pluggable=%d\n", QCASPI_DRV_VERSION, - qcaspi_clkspeed, + spi->max_speed_hz, qcaspi_burst_len, qcaspi_pluggable); spi->mode = SPI_MODE_3; - spi->max_speed_hz = qcaspi_clkspeed; if (spi_setup(spi) < 0) { dev_err(&spi->dev, "Unable to setup SPI device\n"); return -EFAULT; |