diff options
author | David S. Miller <davem@davemloft.net> | 2020-03-22 05:56:04 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-22 05:56:04 +0300 |
commit | 26922c0ef33f2b24192f567db9d01ce4fa289b54 (patch) | |
tree | 395bc732e36148eda5ef33c41a0e6367f7eb66ce | |
parent | 6fcd42242ebcc98ebf1a9a03f5e8cb646277fd78 (diff) | |
parent | a4674f34711b96b65bdc4d54eca88d2fd123bbc6 (diff) | |
download | linux-26922c0ef33f2b24192f567db9d01ce4fa289b54.tar.xz |
Merge branch 'ionic-error-recovery-fixes'
Shannon Nelson says:
====================
ionic error recovery fixes
These are a few little patches to make error recovery a little
more safe and successful.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_debugfs.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_lif.c | 52 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_main.c | 12 |
3 files changed, 50 insertions, 22 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c index bc03cecf80cc..5f8fc58d42b3 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_debugfs.c @@ -228,7 +228,13 @@ DEFINE_SHOW_ATTRIBUTE(netdev); void ionic_debugfs_add_lif(struct ionic_lif *lif) { - lif->dentry = debugfs_create_dir(lif->name, lif->ionic->dentry); + struct dentry *lif_dentry; + + lif_dentry = debugfs_create_dir(lif->name, lif->ionic->dentry); + if (IS_ERR_OR_NULL(lif_dentry)) + return; + lif->dentry = lif_dentry; + debugfs_create_file("netdev", 0400, lif->dentry, lif->netdev, &netdev_fops); } diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 12e3823b0bc1..8b442eb010a2 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -275,8 +275,10 @@ static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) if (qcq->flags & IONIC_QCQ_F_INTR) { ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, IONIC_INTR_MASK_SET); + irq_set_affinity_hint(qcq->intr.vector, NULL); devm_free_irq(dev, qcq->intr.vector, &qcq->napi); netif_napi_del(&qcq->napi); + qcq->intr.vector = 0; } qcq->flags &= ~IONIC_QCQ_F_INITED; @@ -318,19 +320,21 @@ static void ionic_qcqs_free(struct ionic_lif *lif) lif->adminqcq = NULL; } - for (i = 0; i < lif->nxqs; i++) - if (lif->rxqcqs[i].stats) - devm_kfree(dev, lif->rxqcqs[i].stats); - - devm_kfree(dev, lif->rxqcqs); - lif->rxqcqs = NULL; - - for (i = 0; i < lif->nxqs; i++) - if (lif->txqcqs[i].stats) - devm_kfree(dev, lif->txqcqs[i].stats); + if (lif->rxqcqs) { + for (i = 0; i < lif->nxqs; i++) + if (lif->rxqcqs[i].stats) + devm_kfree(dev, lif->rxqcqs[i].stats); + devm_kfree(dev, lif->rxqcqs); + lif->rxqcqs = NULL; + } - devm_kfree(dev, lif->txqcqs); - lif->txqcqs = NULL; + if (lif->txqcqs) { + for (i = 0; i < lif->nxqs; i++) + if (lif->txqcqs[i].stats) + devm_kfree(dev, lif->txqcqs[i].stats); + devm_kfree(dev, lif->txqcqs); + lif->txqcqs = NULL; + } } static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq, @@ -832,7 +836,7 @@ static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN); err = ionic_adminq_post_wait(lif, &ctx); - if (err) + if (err && err != -EEXIST) return err; return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx); @@ -862,7 +866,7 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) spin_unlock_bh(&lif->rx_filters.lock); err = ionic_adminq_post_wait(lif, &ctx); - if (err) + if (err && err != -EEXIST) return err; netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", addr, @@ -1425,10 +1429,15 @@ static void ionic_lif_rss_deinit(struct ionic_lif *lif) static void ionic_txrx_disable(struct ionic_lif *lif) { unsigned int i; + int err; for (i = 0; i < lif->nxqs; i++) { - ionic_qcq_disable(lif->txqcqs[i].qcq); - ionic_qcq_disable(lif->rxqcqs[i].qcq); + err = ionic_qcq_disable(lif->txqcqs[i].qcq); + if (err == -ETIMEDOUT) + break; + err = ionic_qcq_disable(lif->rxqcqs[i].qcq); + if (err == -ETIMEDOUT) + break; } } @@ -1552,7 +1561,8 @@ static int ionic_txrx_enable(struct ionic_lif *lif) ionic_rx_fill(&lif->rxqcqs[i].qcq->q); err = ionic_qcq_enable(lif->rxqcqs[i].qcq); if (err) { - ionic_qcq_disable(lif->txqcqs[i].qcq); + if (err != -ETIMEDOUT) + ionic_qcq_disable(lif->txqcqs[i].qcq); goto err_out; } } @@ -1561,8 +1571,12 @@ static int ionic_txrx_enable(struct ionic_lif *lif) err_out: while (i--) { - ionic_qcq_disable(lif->rxqcqs[i].qcq); - ionic_qcq_disable(lif->txqcqs[i].qcq); + err = ionic_qcq_disable(lif->rxqcqs[i].qcq); + if (err == -ETIMEDOUT) + break; + err = ionic_qcq_disable(lif->txqcqs[i].qcq); + if (err == -ETIMEDOUT) + break; } return err; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index c5e3d7639f7e..c16dbbe54bf7 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -243,11 +243,16 @@ static void ionic_adminq_cb(struct ionic_queue *q, static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) { - struct ionic_queue *adminq = &lif->adminqcq->q; + struct ionic_queue *adminq; int err = 0; WARN_ON(in_interrupt()); + if (!lif->adminqcq) + return -EIO; + + adminq = &lif->adminqcq->q; + spin_lock(&lif->adminq_lock); if (!ionic_q_has_space(adminq, 1)) { err = -ENOSPC; @@ -360,7 +365,10 @@ try_again: done, duration / HZ, duration); if (!done && hb) { - ionic_dev_cmd_clean(ionic); + /* It is possible (but unlikely) that FW was busy and missed a + * heartbeat check but is still alive and will process this + * request, so don't clean the dev_cmd in this case. + */ dev_warn(ionic->dev, "DEVCMD %s (%d) failed - FW halted\n", ionic_opcode_to_str(opcode), opcode); return -ENXIO; |