[PATCH net-next 1/7] ionic: tx and rx queues state follows link state
From: Shannon Nelson <hidden>
Date: 2020-03-12 21:50:31
Subsystem:
networking drivers, pensando ethernet drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Brett Creeley, Linus Torvalds
When link goes down, tear down the Tx and Rx queues. When link comes back up, rebuild the queues. This lets us release memory resources for devices that aren't going to use them, and prepares us for support of fw upgrade. We also add a couple of checks on tear down to watch out for structs already torn down. Signed-off-by: Shannon Nelson <redacted> --- .../net/ethernet/pensando/ionic/ionic_lif.c | 76 +++++++++++++------ .../net/ethernet/pensando/ionic/ionic_main.c | 7 +- 2 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index aaf4a40fa98b..682f4b5af704 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c@@ -73,6 +73,11 @@ static void ionic_link_status_check(struct ionic_lif *lif) u16 link_status; bool link_up; + if (lif->ionic->is_mgmt_nic) { + clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state); + return; + } + link_status = le16_to_cpu(lif->info->status.link_status); link_up = link_status == IONIC_PORT_OPER_STATUS_UP;
@@ -81,20 +86,28 @@ static void ionic_link_status_check(struct ionic_lif *lif) goto link_out; if (link_up) { - netdev_info(netdev, "Link up - %d Gbps\n", - le32_to_cpu(lif->info->status.link_speed) / 1000); + u32 link_speed; - if (test_bit(IONIC_LIF_F_UP, lif->state)) { - netif_tx_wake_all_queues(lif->netdev); - netif_carrier_on(netdev); + link_speed = le16_to_cpu(lif->info->status.link_speed); + netdev_info(netdev, "Link up - %d Gbps\n", link_speed / 1000); + + if (!test_bit(IONIC_LIF_F_UP, lif->state) && + netif_running(netdev)) { + rtnl_lock(); + ionic_open(netdev); + rtnl_unlock(); } + + netif_carrier_on(netdev); } else { netdev_info(netdev, "Link down\n"); - - /* carrier off first to avoid watchdog timeout */ netif_carrier_off(netdev); - if (test_bit(IONIC_LIF_F_UP, lif->state)) - netif_tx_stop_all_queues(netdev); + + if (test_bit(IONIC_LIF_F_UP, lif->state)) { + rtnl_lock(); + ionic_stop(netdev); + rtnl_unlock(); + } } link_out:
@@ -275,8 +288,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 +333,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,
@@ -1573,7 +1590,17 @@ int ionic_open(struct net_device *netdev) struct ionic_lif *lif = netdev_priv(netdev); int err; - netif_carrier_off(netdev); + if (test_bit(IONIC_LIF_F_UP, lif->state)) { + dev_dbg(lif->ionic->dev, "%s: %s called when state=UP\n", + __func__, lif->name); + return 0; + } + + ionic_link_status_check_request(lif); + + /* wait until carrier is up before creating rx and tx queues */ + if (!netif_carrier_ok(lif->netdev)) + return 0; err = ionic_txrx_alloc(lif); if (err)
@@ -1592,7 +1619,6 @@ int ionic_open(struct net_device *netdev) set_bit(IONIC_LIF_F_UP, lif->state); - ionic_link_status_check_request(lif); if (netif_carrier_ok(netdev)) netif_tx_wake_all_queues(netdev);
@@ -1611,7 +1637,7 @@ int ionic_stop(struct net_device *netdev) int err = 0; if (!test_bit(IONIC_LIF_F_UP, lif->state)) { - dev_dbg(lif->ionic->dev, "%s: %s state=DOWN\n", + dev_dbg(lif->ionic->dev, "%s: %s called when state=DOWN\n", __func__, lif->name); return 0; }
@@ -1922,6 +1948,8 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index ionic_ethtool_set_ops(netdev); netdev->watchdog_timeo = 2 * HZ; + netif_carrier_off(netdev); + netdev->min_mtu = IONIC_MIN_MTU; netdev->max_mtu = IONIC_MAX_MTU;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c
index e4a76e66f542..40345281b2c9 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c@@ -240,11 +240,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;
--
2.17.1