diff mbox series

[net-next,1/7] ionic: tx and rx queues state follows link state

Message ID 20200312215015.69547-2-snelson@pensando.io
State New
Headers show
Series [net-next,1/7] ionic: tx and rx queues state follows link state | expand

Commit Message

Shannon Nelson March 12, 2020, 9:50 p.m. UTC
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 <snelson@pensando.io>
---
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 76 +++++++++++++------
 .../net/ethernet/pensando/ionic/ionic_main.c  |  7 +-
 2 files changed, 58 insertions(+), 25 deletions(-)
diff mbox series

Patch

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;