aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/enic
diff options
context:
space:
mode:
authorRoopa Prabhu <roprabhu@cisco.com>2011-06-03 10:35:17 -0400
committerDavid S. Miller <davem@davemloft.net>2011-06-07 01:48:47 -0400
commitc97c894dc7bcae28d0308dbcd010185079de4a28 (patch)
tree777ffc3509de41fb3cb0c182e9f6ef69e6f1c698 /drivers/net/enic
parent8d13e670d3fb83f4668c9e37196c3bbf5b9f094c (diff)
enic: Add support for MTU change via port profile on a dynamic vnic
enic driver gets MTU change notifications for MTU changes in the port profile associated to a dynamic vnic. This patch adds support in enic driver to set new MTU on the dynamic vnic and dynamically adjust its buffers with new MTU size in response to such notifications. Signed-off-by: Roopa Prabhu <roprabhu@cisco.com> Signed-off-by: Vasanthy Kolluri <vkolluri@cisco.com> Signed-off-by: David Wang <dwang2@cisco.com> Signed-off-by: Christian Benvenuti <benve@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/enic')
-rw-r--r--drivers/net/enic/enic.h3
-rw-r--r--drivers/net/enic/enic_main.c71
2 files changed, 68 insertions, 6 deletions
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 38b351c7b979..e0d2ad181bb8 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -32,7 +32,7 @@
32 32
33#define DRV_NAME "enic" 33#define DRV_NAME "enic"
34#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" 34#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
35#define DRV_VERSION "2.1.1.13" 35#define DRV_VERSION "2.1.1.16"
36#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc" 36#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
37 37
38#define ENIC_BARS_MAX 6 38#define ENIC_BARS_MAX 6
@@ -74,6 +74,7 @@ struct enic {
74 struct vnic_dev *vdev; 74 struct vnic_dev *vdev;
75 struct timer_list notify_timer; 75 struct timer_list notify_timer;
76 struct work_struct reset; 76 struct work_struct reset;
77 struct work_struct change_mtu_work;
77 struct msix_entry msix_entry[ENIC_INTR_MAX]; 78 struct msix_entry msix_entry[ENIC_INTR_MAX];
78 struct enic_msix_entry msix[ENIC_INTR_MAX]; 79 struct enic_msix_entry msix[ENIC_INTR_MAX];
79 u32 msg_enable; 80 u32 msg_enable;
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 5b087ebe632d..1daf79b36165 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -423,11 +423,18 @@ static void enic_mtu_check(struct enic *enic)
423 423
424 if (mtu && mtu != enic->port_mtu) { 424 if (mtu && mtu != enic->port_mtu) {
425 enic->port_mtu = mtu; 425 enic->port_mtu = mtu;
426 if (mtu < netdev->mtu) 426 if (enic_is_dynamic(enic)) {
427 netdev_warn(netdev, 427 mtu = max_t(int, ENIC_MIN_MTU,
428 "interface MTU (%d) set higher " 428 min_t(int, ENIC_MAX_MTU, mtu));
429 "than switch port MTU (%d)\n", 429 if (mtu != netdev->mtu)
430 netdev->mtu, mtu); 430 schedule_work(&enic->change_mtu_work);
431 } else {
432 if (mtu < netdev->mtu)
433 netdev_warn(netdev,
434 "interface MTU (%d) set higher "
435 "than switch port MTU (%d)\n",
436 netdev->mtu, mtu);
437 }
431 } 438 }
432} 439}
433 440
@@ -1688,6 +1695,9 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
1688 if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU) 1695 if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
1689 return -EINVAL; 1696 return -EINVAL;
1690 1697
1698 if (enic_is_dynamic(enic))
1699 return -EOPNOTSUPP;
1700
1691 if (running) 1701 if (running)
1692 enic_stop(netdev); 1702 enic_stop(netdev);
1693 1703
@@ -1704,6 +1714,55 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
1704 return 0; 1714 return 0;
1705} 1715}
1706 1716
1717static void enic_change_mtu_work(struct work_struct *work)
1718{
1719 struct enic *enic = container_of(work, struct enic, change_mtu_work);
1720 struct net_device *netdev = enic->netdev;
1721 int new_mtu = vnic_dev_mtu(enic->vdev);
1722 int err;
1723 unsigned int i;
1724
1725 new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu));
1726
1727 rtnl_lock();
1728
1729 /* Stop RQ */
1730 del_timer_sync(&enic->notify_timer);
1731
1732 for (i = 0; i < enic->rq_count; i++)
1733 napi_disable(&enic->napi[i]);
1734
1735 vnic_intr_mask(&enic->intr[0]);
1736 enic_synchronize_irqs(enic);
1737 err = vnic_rq_disable(&enic->rq[0]);
1738 if (err) {
1739 netdev_err(netdev, "Unable to disable RQ.\n");
1740 return;
1741 }
1742 vnic_rq_clean(&enic->rq[0], enic_free_rq_buf);
1743 vnic_cq_clean(&enic->cq[0]);
1744 vnic_intr_clean(&enic->intr[0]);
1745
1746 /* Fill RQ with new_mtu-sized buffers */
1747 netdev->mtu = new_mtu;
1748 vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
1749 /* Need at least one buffer on ring to get going */
1750 if (vnic_rq_desc_used(&enic->rq[0]) == 0) {
1751 netdev_err(netdev, "Unable to alloc receive buffers.\n");
1752 return;
1753 }
1754
1755 /* Start RQ */
1756 vnic_rq_enable(&enic->rq[0]);
1757 napi_enable(&enic->napi[0]);
1758 vnic_intr_unmask(&enic->intr[0]);
1759 enic_notify_timer_start(enic);
1760
1761 rtnl_unlock();
1762
1763 netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu);
1764}
1765
1707#ifdef CONFIG_NET_POLL_CONTROLLER 1766#ifdef CONFIG_NET_POLL_CONTROLLER
1708static void enic_poll_controller(struct net_device *netdev) 1767static void enic_poll_controller(struct net_device *netdev)
1709{ 1768{
@@ -2345,6 +2404,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
2345 enic->notify_timer.data = (unsigned long)enic; 2404 enic->notify_timer.data = (unsigned long)enic;
2346 2405
2347 INIT_WORK(&enic->reset, enic_reset); 2406 INIT_WORK(&enic->reset, enic_reset);
2407 INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
2348 2408
2349 for (i = 0; i < enic->wq_count; i++) 2409 for (i = 0; i < enic->wq_count; i++)
2350 spin_lock_init(&enic->wq_lock[i]); 2410 spin_lock_init(&enic->wq_lock[i]);
@@ -2427,6 +2487,7 @@ static void __devexit enic_remove(struct pci_dev *pdev)
2427 struct enic *enic = netdev_priv(netdev); 2487 struct enic *enic = netdev_priv(netdev);
2428 2488
2429 cancel_work_sync(&enic->reset); 2489 cancel_work_sync(&enic->reset);
2490 cancel_work_sync(&enic->change_mtu_work);
2430 unregister_netdev(netdev); 2491 unregister_netdev(netdev);
2431 enic_dev_deinit(enic); 2492 enic_dev_deinit(enic);
2432 vnic_dev_close(enic->vdev); 2493 vnic_dev_close(enic->vdev);