summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/cisco/enic/enic_main.c
diff options
context:
space:
mode:
authorGovindarajulu Varadarajan <_govind@gmx.com>2015-10-01 14:18:47 +0530
committerDavid S. Miller <davem@davemloft.net>2015-10-05 03:51:35 -0700
commit937317c7c1097aa878a5000e3aab616eb5c590c0 (patch)
tree8360a5079b034204940f3adc686f8a7b543ef34b /drivers/net/ethernet/cisco/enic/enic_main.c
parentcc809237e1f215141165f221ad729803d88bcbbe (diff)
downloadop-kernel-dev-937317c7c1097aa878a5000e3aab616eb5c590c0.zip
op-kernel-dev-937317c7c1097aa878a5000e3aab616eb5c590c0.tar.gz
enic: do hang reset only in case of tx timeout
The current code invokes hang reset in case of error interrupt. We should hang reset only in case of tx timeout. This because of the way hang reset is implemented in firmware. Hang reset takes more firmware resources than soft reset. Adaptor does not generate error interrupt in case of tx timeout. Hang reset only in case of tx timeout, in .ndo_tx_timeout. Do soft reset otherwise. Introduce deferred work, enic_tx_hang_reset, to do hang reset. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cisco/enic/enic_main.c')
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 0b54429..0c22fd0 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -808,7 +808,7 @@ static void enic_set_rx_mode(struct net_device *netdev)
static void enic_tx_timeout(struct net_device *netdev)
{
struct enic *enic = netdev_priv(netdev);
- schedule_work(&enic->reset);
+ schedule_work(&enic->tx_hang_reset);
}
static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
@@ -1928,6 +1928,19 @@ static int enic_dev_open(struct enic *enic)
return err;
}
+static int enic_dev_soft_reset(struct enic *enic)
+{
+ int err;
+
+ err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset,
+ vnic_dev_soft_reset_done, 0);
+ if (err)
+ netdev_err(enic->netdev, "vNIC soft reset failed, err %d\n",
+ err);
+
+ return err;
+}
+
static int enic_dev_hang_reset(struct enic *enic)
{
int err;
@@ -2064,6 +2077,26 @@ static void enic_reset(struct work_struct *work)
rtnl_lock();
spin_lock(&enic->enic_api_lock);
+ enic_stop(enic->netdev);
+ enic_dev_soft_reset(enic);
+ enic_reset_addr_lists(enic);
+ enic_init_vnic_resources(enic);
+ enic_set_rss_nic_cfg(enic);
+ enic_dev_set_ig_vlan_rewrite_mode(enic);
+ enic_open(enic->netdev);
+ spin_unlock(&enic->enic_api_lock);
+ call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
+
+ rtnl_unlock();
+}
+
+static void enic_tx_hang_reset(struct work_struct *work)
+{
+ struct enic *enic = container_of(work, struct enic, tx_hang_reset);
+
+ rtnl_lock();
+
+ spin_lock(&enic->enic_api_lock);
enic_dev_hang_notify(enic);
enic_stop(enic->netdev);
enic_dev_hang_reset(enic);
@@ -2587,6 +2620,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
enic_set_rx_coal_setting(enic);
INIT_WORK(&enic->reset, enic_reset);
+ INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
for (i = 0; i < enic->wq_count; i++)
OpenPOWER on IntegriCloud