i40evf: request reset on tx hang
authorMitch Williams <mitch.a.williams@intel.com>
Fri, 21 Feb 2014 03:29:05 +0000 (19:29 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 21 Feb 2014 17:38:25 +0000 (12:38 -0500)
If the kernel watchdog bites us, ask the PF to reset us and attempt to
reinit the driver.

Change-ID: Ic97665aeeed71ce712b9c4f057e78ff8372522b9
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/intel/i40evf/i40evf.h
drivers/net/ethernet/intel/i40evf/i40evf_main.c
drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c

index ef7ce65bc00ad2b72f78bd6cf4321b16e13a3da3..c9a5056015beeccd4fcdb2e7ee5872719297137d 100644 (file)
@@ -287,6 +287,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter);
 void i40evf_del_vlans(struct i40evf_adapter *adapter);
 void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags);
 void i40evf_request_stats(struct i40evf_adapter *adapter);
+void i40evf_request_reset(struct i40evf_adapter *adapter);
 void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
                                enum i40e_virtchnl_ops v_opcode,
                                i40e_status v_retval, u8 *msg, u16 msglen);
index fe2271e19423a70b7dae20dd4b3b0b5f93aa5d8b..1629b73d281a233d0333ebf68b860041152d87b9 100644 (file)
@@ -167,9 +167,13 @@ static void i40evf_tx_timeout(struct net_device *netdev)
        struct i40evf_adapter *adapter = netdev_priv(netdev);
 
        adapter->tx_timeout_count++;
-
-       /* Do the reset outside of interrupt context */
-       schedule_work(&adapter->reset_task);
+       dev_info(&adapter->pdev->dev, "TX timeout detected.\n");
+       if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING)) {
+               dev_info(&adapter->pdev->dev, "Requesting reset from PF\n");
+               i40evf_request_reset(adapter);
+               adapter->flags |= I40EVF_FLAG_RESET_PENDING;
+               schedule_work(&adapter->reset_task);
+       }
 }
 
 /**
index 93891a114d3f08c018c38dd7f6c4672a775dc402..e294f012647d801417af4ca1f68d0629cbaf08cc 100644 (file)
@@ -654,6 +654,18 @@ void i40evf_request_stats(struct i40evf_adapter *adapter)
                /* if the request failed, don't lock out others */
                adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
 }
+/**
+ * i40evf_request_reset
+ * @adapter: adapter structure
+ *
+ * Request that the PF reset this VF. No response is expected.
+ **/
+void i40evf_request_reset(struct i40evf_adapter *adapter)
+{
+       /* Don't check CURRENT_OP - this is always higher priority */
+       i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_RESET_VF, NULL, 0);
+       adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
+}
 
 /**
  * i40evf_virtchnl_completion