From: Mitch Williams Date: Fri, 21 Feb 2014 03:29:05 +0000 (-0800) Subject: i40evf: request reset on tx hang X-Git-Tag: firefly_0821_release~176^2~4167^2~288^2~13 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=625777e3861f0e664174dc95696328c7c5b0e4b3;p=firefly-linux-kernel-4.4.55.git i40evf: request reset on tx hang 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 Signed-off-by: Jesse Brandeburg Tested-by: Sibai Li Signed-off-by: Aaron Brown Signed-off-by: David S. Miller --- diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index ef7ce65bc00a..c9a5056015be 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -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); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index fe2271e19423..1629b73d281a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -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); + } } /** diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 93891a114d3f..e294f012647d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -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