net/ionic: improve link state handling
authorAndrew Boyer <aboyer@pensando.io>
Wed, 16 Dec 2020 21:12:55 +0000 (13:12 -0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 13 Jan 2021 17:51:58 +0000 (18:51 +0100)
Add UP and FW_RESET state flags.
Update the stack info when the link state changes.
Convert set_link_up/set_link_down to lif_start/lif_stop.
Condition reported link state on UP flag.

Signed-off-by: Andrew Boyer <aboyer@pensando.io>
drivers/net/ionic/ionic_ethdev.c
drivers/net/ionic/ionic_ethdev.h
drivers/net/ionic/ionic_lif.c
drivers/net/ionic/ionic_lif.h

index 7ab32a0..fd7cd51 100644 (file)
@@ -28,8 +28,6 @@ static int  ionic_dev_stop(struct rte_eth_dev *dev);
 static int  ionic_dev_close(struct rte_eth_dev *dev);
 static int  ionic_dev_set_link_up(struct rte_eth_dev *dev);
 static int  ionic_dev_set_link_down(struct rte_eth_dev *dev);
-static int  ionic_dev_link_update(struct rte_eth_dev *eth_dev,
-       int wait_to_complete);
 static int  ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev,
        struct rte_eth_fc_conf *fc_conf);
 static int  ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev,
@@ -236,21 +234,17 @@ static int
 ionic_dev_set_link_up(struct rte_eth_dev *eth_dev)
 {
        struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
-       struct ionic_adapter *adapter = lif->adapter;
-       struct ionic_dev *idev = &adapter->idev;
        int err;
 
        IONIC_PRINT_CALL();
 
-       ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP);
+       err = ionic_lif_start(lif);
+       if (err)
+               IONIC_PRINT(ERR, "Could not start lif to set link up");
 
-       err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
-       if (err) {
-               IONIC_PRINT(WARNING, "Failed to bring port UP");
-               return err;
-       }
+       ionic_dev_link_update(lif->eth_dev, 0);
 
-       return 0;
+       return err;
 }
 
 /*
@@ -260,24 +254,17 @@ static int
 ionic_dev_set_link_down(struct rte_eth_dev *eth_dev)
 {
        struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
-       struct ionic_adapter *adapter = lif->adapter;
-       struct ionic_dev *idev = &adapter->idev;
-       int err;
 
        IONIC_PRINT_CALL();
 
-       ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_DOWN);
+       ionic_lif_stop(lif);
 
-       err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
-       if (err) {
-               IONIC_PRINT(WARNING, "Failed to bring port DOWN");
-               return err;
-       }
+       ionic_dev_link_update(lif->eth_dev, 0);
 
        return 0;
 }
 
-static int
+int
 ionic_dev_link_update(struct rte_eth_dev *eth_dev,
                int wait_to_complete __rte_unused)
 {
@@ -291,7 +278,8 @@ ionic_dev_link_update(struct rte_eth_dev *eth_dev,
        memset(&link, 0, sizeof(link));
        link.link_autoneg = ETH_LINK_AUTONEG;
 
-       if (!adapter->link_up) {
+       if (!adapter->link_up ||
+           !(lif->state & IONIC_LIF_F_UP)) {
                /* Interface is down */
                link.link_status = ETH_LINK_DOWN;
                link.link_duplex = ETH_LINK_HALF_DUPLEX;
@@ -944,15 +932,12 @@ static int
 ionic_dev_stop(struct rte_eth_dev *eth_dev)
 {
        struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
-       int err;
 
        IONIC_PRINT_CALL();
 
-       err = ionic_lif_stop(lif);
-       if (err)
-               IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
+       ionic_lif_stop(lif);
 
-       return err;
+       return 0;
 }
 
 static void ionic_unconfigure_intr(struct ionic_adapter *adapter);
@@ -965,17 +950,12 @@ ionic_dev_close(struct rte_eth_dev *eth_dev)
 {
        struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
        struct ionic_adapter *adapter = lif->adapter;
-       int err;
 
        IONIC_PRINT_CALL();
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
-       err = ionic_lif_stop(lif);
-       if (err) {
-               IONIC_PRINT(ERR, "Cannot stop LIF: %d", err);
-               return -1;
-       }
+       ionic_lif_stop(lif);
 
        ionic_lif_free_queues(lif);
 
@@ -1076,6 +1056,9 @@ eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev)
        ionic_lif_deinit(lif);
        ionic_lif_free(lif);
 
+       if (!(lif->state & IONIC_LIF_F_FW_RESET))
+               ionic_lif_reset(lif);
+
        return 0;
 }
 
index 578e230..6cbcd0f 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef _IONIC_ETHDEV_H_
 #define _IONIC_ETHDEV_H_
 
+#include <rte_ethdev.h>
+
 #define IONIC_ETH_RSS_OFFLOAD_ALL ( \
        ETH_RSS_IPV4 | \
        ETH_RSS_NONFRAG_IPV4_TCP | \
@@ -18,5 +20,7 @@
 #define IONIC_ETH_DEV_TO_ADAPTER(eth_dev) \
        (IONIC_ETH_DEV_TO_LIF(eth_dev)->adapter)
 
+int ionic_dev_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete);
+
 #endif /* _IONIC_ETHDEV_H_ */
 
index 9b11e63..c1a95ca 100644 (file)
@@ -63,12 +63,12 @@ ionic_qcq_disable(struct ionic_qcq *qcq)
        return ionic_adminq_post_wait(lif, &ctx);
 }
 
-int
-ionic_lif_stop(struct ionic_lif *lif __rte_unused)
+void
+ionic_lif_stop(struct ionic_lif *lif)
 {
-       /* Carrier OFF here */
+       IONIC_PRINT_CALL();
 
-       return 0;
+       lif->state &= ~IONIC_LIF_F_UP;
 }
 
 void
@@ -1098,14 +1098,32 @@ ionic_link_status_check(struct ionic_lif *lif)
                return;
 
        if (link_up) {
-               IONIC_PRINT(DEBUG, "Link up - %d Gbps",
-                       lif->info->status.link_speed);
                adapter->link_speed = lif->info->status.link_speed;
+               IONIC_PRINT(DEBUG, "Link up - %d Gbps",
+                       adapter->link_speed);
        } else {
                IONIC_PRINT(DEBUG, "Link down");
        }
 
        adapter->link_up = link_up;
+       ionic_dev_link_update(lif->eth_dev, 0);
+}
+
+static void
+ionic_lif_handle_fw_down(struct ionic_lif *lif)
+{
+       if (lif->state & IONIC_LIF_F_FW_RESET)
+               return;
+
+       lif->state |= IONIC_LIF_F_FW_RESET;
+
+       if (lif->state & IONIC_LIF_F_UP) {
+               IONIC_PRINT(NOTICE,
+                       "Surprise FW stop, stopping %s\n", lif->name);
+               ionic_lif_stop(lif);
+       }
+
+       IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
 }
 
 static bool
@@ -1127,14 +1145,27 @@ ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
        switch (cq_desc->event.ecode) {
        case IONIC_EVENT_LINK_CHANGE:
                IONIC_PRINT(DEBUG,
-                       "Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
+                       "Notifyq IONIC_EVENT_LINK_CHANGE %s "
+                       "eid=%jd link_status=%d link_speed=%d",
+                       lif->name,
                        cq_desc->event.eid,
                        cq_desc->link_change.link_status,
                        cq_desc->link_change.link_speed);
 
                lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
+               break;
 
+       case IONIC_EVENT_RESET:
+               IONIC_PRINT(NOTICE,
+                       "Notifyq IONIC_EVENT_RESET %s "
+                       "eid=%jd, reset_code=%d state=%d",
+                       lif->name,
+                       cq_desc->event.eid,
+                       cq_desc->reset.reset_code,
+                       cq_desc->reset.state);
+               ionic_lif_handle_fw_down(lif);
                break;
+
        default:
                IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
                        cq_desc->event.ecode, cq_desc->event.eid);
@@ -1618,9 +1649,10 @@ ionic_lif_start(struct ionic_lif *lif)
                }
        }
 
-       ionic_link_status_check(lif);
-
        /* Carrier ON here */
+       lif->state |= IONIC_LIF_F_UP;
+
+       ionic_link_status_check(lif);
 
        return 0;
 }
index cc0e4f0..86d9336 100644 (file)
@@ -77,6 +77,8 @@ struct ionic_qcq {
 
 #define IONIC_LIF_F_INITED             BIT(0)
 #define IONIC_LIF_F_LINK_CHECK_NEEDED  BIT(1)
+#define IONIC_LIF_F_UP                 BIT(2)
+#define IONIC_LIF_F_FW_RESET           BIT(3)
 
 #define IONIC_LIF_NAME_MAX_SZ          (32)
 
@@ -127,7 +129,7 @@ int ionic_lif_init(struct ionic_lif *lif);
 void ionic_lif_deinit(struct ionic_lif *lif);
 
 int ionic_lif_start(struct ionic_lif *lif);
-int ionic_lif_stop(struct ionic_lif *lif);
+void ionic_lif_stop(struct ionic_lif *lif);
 
 int ionic_lif_configure(struct ionic_lif *lif);
 void ionic_lif_reset(struct ionic_lif *lif);