From: Dany Madden <d...@linux.ibm.com>

Currently ibmvnic does not support the disable vnic command from the
Hardware Management Console. This patch enables ibmvnic to process
CRQ message 0x07, disable vnic adapter.

Signed-off-by: Dany Madden <d...@linux.ibm.com>
---
 drivers/net/ethernet/ibm/ibmvnic.c | 40 ++++++++++++++++++++++++++++++
 drivers/net/ethernet/ibm/ibmvnic.h |  3 ++-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c 
b/drivers/net/ethernet/ibm/ibmvnic.c
index dcb23015b6b4..82074e503ba9 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -109,6 +109,8 @@ static void release_crq_queue(struct ibmvnic_adapter *);
 static int __ibmvnic_set_mac(struct net_device *, u8 *);
 static int init_crq_queue(struct ibmvnic_adapter *adapter);
 static int send_query_phys_parms(struct ibmvnic_adapter *adapter);
+static void ibmvnic_disable(struct ibmvnic_adapter *adapter);
+static int ibmvnic_close(struct net_device *netdev);
 
 struct ibmvnic_stat {
        char name[ETH_GSTRING_LEN];
@@ -1209,6 +1211,42 @@ static int ibmvnic_open(struct net_device *netdev)
        return rc;
 }
 
+static void ibmvnic_disable(struct ibmvnic_adapter *adapter)
+{
+       struct list_head *entry, *tmp_entry;
+       struct net_device *netdev = adapter->netdev;
+       int rc = 0;
+
+       /* cancel all pending resets in the queue */
+       if (!list_empty(&adapter->rwi_list)) {
+               list_for_each_safe(entry, tmp_entry, &adapter->rwi_list)
+                       list_del(entry);
+       }
+
+       /* wait for current reset to finish */
+       flush_work(&adapter->ibmvnic_reset);
+       flush_delayed_work(&adapter->ibmvnic_delayed_reset);
+
+       if (test_bit(0, &adapter->resetting) ||
+           adapter->state == VNIC_PROBED ||
+           adapter->state == VNIC_OPEN ||
+           adapter->state == VNIC_OPENING) {
+               rc = ibmvnic_close(netdev);
+               /* Expect -EINVAL when crq is no longer active. Set link down
+                * would fail.
+                */
+               if (rc && rc != -EINVAL) {
+                       netdev_err(netdev, "Failed to disable adapter, 
rc=%d\n", rc);
+                       return;
+               }
+       } else {
+               netdev_dbg(netdev, "Disable adapter request ignored 
(state=%d)\n", adapter->state);
+               return;
+       }
+
+       netdev_dbg(netdev, "Adapter disabled\n");
+}
+
 static void clean_rx_pools(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_rx_pool *rx_pool;
@@ -4789,6 +4827,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                } else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) {
                        dev_info(dev, "Backing device failover detected\n");
                        adapter->failover_pending = true;
+               } else if (gen_crq->cmd == IBMVNIC_DEVICE_DISABLE) {
+                       ibmvnic_disable(adapter);
                } else {
                        /* The adapter lost the connection */
                        dev_err(dev, "Virtual Adapter failed (rc=%d)\n",
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h 
b/drivers/net/ethernet/ibm/ibmvnic.h
index 217dcc7ded70..af68f85534bc 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h
@@ -834,10 +834,11 @@ enum ibmvnic_crq_type {
        IBMVNIC_CRQ_XPORT_EVENT         = 0xFF,
 };
 
-enum ibmvfc_crq_format {
+enum ibmvnic_crq_format {
        IBMVNIC_CRQ_INIT                 = 0x01,
        IBMVNIC_CRQ_INIT_COMPLETE        = 0x02,
        IBMVNIC_PARTITION_MIGRATED       = 0x06,
+       IBMVNIC_DEVICE_DISABLE           = 0x07,
        IBMVNIC_DEVICE_FAILOVER          = 0x08,
 };
 
-- 
2.23.0

Reply via email to