diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc/igc_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 84 | 
1 files changed, 65 insertions, 19 deletions
| diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 44b1740dc098..25fc6c65209b 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -2942,7 +2942,9 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)  		if (tx_buffer->next_to_watch &&  		    time_after(jiffies, tx_buffer->time_stamp +  		    (adapter->tx_timeout_factor * HZ)) && -		    !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF)) { +		    !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) && +		    (rd32(IGC_TDH(tx_ring->reg_idx)) != +		     readl(tx_ring->tail))) {  			/* detected Tx unit hang */  			netdev_err(tx_ring->netdev,  				   "Detected Tx Unit Hang\n" @@ -5069,6 +5071,24 @@ static int igc_change_mtu(struct net_device *netdev, int new_mtu)  }  /** + * igc_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + * @txqueue: queue number that timed out + **/ +static void igc_tx_timeout(struct net_device *netdev, +			   unsigned int __always_unused txqueue) +{ +	struct igc_adapter *adapter = netdev_priv(netdev); +	struct igc_hw *hw = &adapter->hw; + +	/* Do the reset outside of interrupt context */ +	adapter->tx_timeout_count++; +	schedule_work(&adapter->reset_task); +	wr32(IGC_EICS, +	     (adapter->eims_enable_mask & ~adapter->eims_other)); +} + +/**   * igc_get_stats64 - Get System Network Statistics   * @netdev: network interface device structure   * @stats: rtnl_link_stats64 pointer @@ -5495,7 +5515,7 @@ static void igc_watchdog_task(struct work_struct *work)  			case SPEED_100:  			case SPEED_1000:  			case SPEED_2500: -				adapter->tx_timeout_factor = 7; +				adapter->tx_timeout_factor = 1;  				break;  			} @@ -5958,6 +5978,7 @@ static bool validate_schedule(struct igc_adapter *adapter,  			      const struct tc_taprio_qopt_offload *qopt)  {  	int queue_uses[IGC_MAX_TX_QUEUES] = { }; +	struct igc_hw *hw = &adapter->hw;  	struct timespec64 now;  	size_t n; @@ -5970,8 +5991,10 @@ static bool validate_schedule(struct igc_adapter *adapter,  	 * in the future, it will hold all the packets until that  	 * time, causing a lot of TX Hangs, so to avoid that, we  	 * reject schedules that would start in the future. +	 * Note: Limitation above is no longer in i226.  	 */ -	if (!is_base_time_past(qopt->base_time, &now)) +	if (!is_base_time_past(qopt->base_time, &now) && +	    igc_is_device_id_i225(hw))  		return false;  	for (n = 0; n < qopt->num_entries; n++) { @@ -5987,18 +6010,18 @@ static bool validate_schedule(struct igc_adapter *adapter,  		if (e->command != TC_TAPRIO_CMD_SET_GATES)  			return false; -		for (i = 0; i < adapter->num_tx_queues; i++) { -			if (e->gate_mask & BIT(i)) +		for (i = 0; i < adapter->num_tx_queues; i++) +			if (e->gate_mask & BIT(i)) {  				queue_uses[i]++; -			/* There are limitations: A single queue cannot be -			 * opened and closed multiple times per cycle unless the -			 * gate stays open. Check for it. -			 */ -			if (queue_uses[i] > 1 && -			    !(prev->gate_mask & BIT(i))) -				return false; -		} +				/* There are limitations: A single queue cannot +				 * be opened and closed multiple times per cycle +				 * unless the gate stays open. Check for it. +				 */ +				if (queue_uses[i] > 1 && +				    !(prev->gate_mask & BIT(i))) +					return false; +			}  	}  	return true; @@ -6041,6 +6064,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,  				 struct tc_taprio_qopt_offload *qopt)  {  	bool queue_configured[IGC_MAX_TX_QUEUES] = { }; +	struct igc_hw *hw = &adapter->hw;  	u32 start_time = 0, end_time = 0;  	size_t n;  	int i; @@ -6053,7 +6077,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,  	if (qopt->base_time < 0)  		return -ERANGE; -	if (adapter->base_time) +	if (igc_is_device_id_i225(hw) && adapter->base_time)  		return -EALREADY;  	if (!validate_schedule(adapter, qopt)) @@ -6201,12 +6225,35 @@ static int igc_tsn_enable_cbs(struct igc_adapter *adapter,  	return igc_tsn_offload_apply(adapter);  } +static int igc_tc_query_caps(struct igc_adapter *adapter, +			     struct tc_query_caps_base *base) +{ +	struct igc_hw *hw = &adapter->hw; + +	switch (base->type) { +	case TC_SETUP_QDISC_TAPRIO: { +		struct tc_taprio_caps *caps = base->caps; + +		caps->broken_mqprio = true; + +		if (hw->mac.type == igc_i225) +			caps->gate_mask_per_txq = true; + +		return 0; +	} +	default: +		return -EOPNOTSUPP; +	} +} +  static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,  			void *type_data)  {  	struct igc_adapter *adapter = netdev_priv(dev);  	switch (type) { +	case TC_QUERY_CAPS: +		return igc_tc_query_caps(adapter, type_data);  	case TC_SETUP_QDISC_TAPRIO:  		return igc_tsn_enable_qbv_scheduling(adapter, type_data); @@ -6320,6 +6367,7 @@ static const struct net_device_ops igc_netdev_ops = {  	.ndo_set_rx_mode	= igc_set_rx_mode,  	.ndo_set_mac_address	= igc_set_mac,  	.ndo_change_mtu		= igc_change_mtu, +	.ndo_tx_timeout		= igc_tx_timeout,  	.ndo_get_stats64	= igc_get_stats64,  	.ndo_fix_features	= igc_fix_features,  	.ndo_set_features	= igc_set_features, @@ -6430,8 +6478,6 @@ static int igc_probe(struct pci_dev *pdev,  	if (err)  		goto err_pci_reg; -	pci_enable_pcie_error_reporting(pdev); -  	err = pci_enable_ptm(pdev, NULL);  	if (err < 0)  		dev_info(&pdev->dev, "PCIe PTM not supported by PCIe bus/controller\n"); @@ -6529,6 +6575,9 @@ static int igc_probe(struct pci_dev *pdev,  	netdev->mpls_features |= NETIF_F_HW_CSUM;  	netdev->hw_enc_features |= netdev->vlan_features; +	netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | +			       NETDEV_XDP_ACT_XSK_ZEROCOPY; +  	/* MTU range: 68 - 9216 */  	netdev->min_mtu = ETH_MIN_MTU;  	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; @@ -6636,7 +6685,6 @@ err_sw_init:  err_ioremap:  	free_netdev(netdev);  err_alloc_etherdev: -	pci_disable_pcie_error_reporting(pdev);  	pci_release_mem_regions(pdev);  err_pci_reg:  err_dma: @@ -6684,8 +6732,6 @@ static void igc_remove(struct pci_dev *pdev)  	free_netdev(netdev); -	pci_disable_pcie_error_reporting(pdev); -  	pci_disable_device(pdev);  } |