enic: handle mtu change for vf properly
authorGovindarajulu Varadarajan <gvaradar@cisco.com>
Fri, 27 Jul 2018 18:19:29 +0000 (11:19 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Sep 2018 07:20:03 +0000 (09:20 +0200)
[ Upstream commit ab123fe071c9aa9680ecd62eb080eb26cff4892c ]

When driver gets notification for mtu change, driver does not handle it for
all RQs. It handles only RQ[0].

Fix is to use enic_change_mtu() interface to change mtu for vf.

Signed-off-by: Govindarajulu Varadarajan <gvaradar@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/cisco/enic/enic_main.c

index 2e9bab4..f7e7b79 100644 (file)
@@ -1842,10 +1842,32 @@ static int enic_stop(struct net_device *netdev)
        return 0;
 }
 
+static int _enic_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       bool running = netif_running(netdev);
+       int err = 0;
+
+       ASSERT_RTNL();
+       if (running) {
+               err = enic_stop(netdev);
+               if (err)
+                       return err;
+       }
+
+       netdev->mtu = new_mtu;
+
+       if (running) {
+               err = enic_open(netdev);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int enic_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct enic *enic = netdev_priv(netdev);
-       int running = netif_running(netdev);
 
        if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
                return -EINVAL;
@@ -1853,20 +1875,12 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
        if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
                return -EOPNOTSUPP;
 
-       if (running)
-               enic_stop(netdev);
-
-       netdev->mtu = new_mtu;
-
        if (netdev->mtu > enic->port_mtu)
                netdev_warn(netdev,
-                       "interface MTU (%d) set higher than port MTU (%d)\n",
-                       netdev->mtu, enic->port_mtu);
+                           "interface MTU (%d) set higher than port MTU (%d)\n",
+                           netdev->mtu, enic->port_mtu);
 
-       if (running)
-               enic_open(netdev);
-
-       return 0;
+       return _enic_change_mtu(netdev, new_mtu);
 }
 
 static void enic_change_mtu_work(struct work_struct *work)
@@ -1874,47 +1888,9 @@ static void enic_change_mtu_work(struct work_struct *work)
        struct enic *enic = container_of(work, struct enic, change_mtu_work);
        struct net_device *netdev = enic->netdev;
        int new_mtu = vnic_dev_mtu(enic->vdev);
-       int err;
-       unsigned int i;
-
-       new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
 
        rtnl_lock();
-
-       /* Stop RQ */
-       del_timer_sync(&enic->notify_timer);
-
-       for (i = 0; i < enic->rq_count; i++)
-               napi_disable(&enic->napi[i]);
-
-       vnic_intr_mask(&enic->intr[0]);
-       enic_synchronize_irqs(enic);
-       err = vnic_rq_disable(&enic->rq[0]);
-       if (err) {
-               rtnl_unlock();
-               netdev_err(netdev, "Unable to disable RQ.\n");
-               return;
-       }
-       vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
-       vnic_cq_clean(&enic->cq[0]);
-       vnic_intr_clean(&enic->intr[0]);
-
-       /* Fill RQ with new_mtu-sized buffers */
-       netdev->mtu = new_mtu;
-       vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
-       /* Need at least one buffer on ring to get going */
-       if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
-               rtnl_unlock();
-               netdev_err(netdev, "Unable to alloc receive buffers.\n");
-               return;
-       }
-
-       /* Start RQ */
-       vnic_rq_enable(&enic->rq[0]);
-       napi_enable(&enic->napi[0]);
-       vnic_intr_unmask(&enic->intr[0]);
-       enic_notify_timer_start(enic);
-
+       (void)_enic_change_mtu(netdev, new_mtu);
        rtnl_unlock();
 
        netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);