| From foo@baz Sun Aug 26 09:13:00 CEST 2018 |
| From: Govindarajulu Varadarajan <gvaradar@cisco.com> |
| Date: Fri, 27 Jul 2018 11:19:29 -0700 |
| Subject: enic: handle mtu change for vf properly |
| |
| From: Govindarajulu Varadarajan <gvaradar@cisco.com> |
| |
| [ 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 | 78 +++++++++------------------- |
| 1 file changed, 27 insertions(+), 51 deletions(-) |
| |
| --- a/drivers/net/ethernet/cisco/enic/enic_main.c |
| +++ b/drivers/net/ethernet/cisco/enic/enic_main.c |
| @@ -2007,28 +2007,42 @@ static int enic_stop(struct net_device * |
| 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 (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); |
| - |
| - if (running) |
| - enic_open(netdev); |
| + "interface MTU (%d) set higher than port MTU (%d)\n", |
| + netdev->mtu, enic->port_mtu); |
| |
| - return 0; |
| + return _enic_change_mtu(netdev, new_mtu); |
| } |
| |
| static void enic_change_mtu_work(struct work_struct *work) |
| @@ -2036,47 +2050,9 @@ static void enic_change_mtu_work(struct |
| 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); |