Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef021194 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by David S. Miller
Browse files

ixgbe: fix bug when EITR=0 causing no writebacks



writebacks can be held indefinitely by hardware if EITR=0, when
combined with TXDCTL.WTHRESH=8.  When EITR=0, WTHRESH should be
set back to zero.

Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f8d1dcaf
Loading
Loading
Loading
Loading
+19 −12
Original line number Original line Diff line number Diff line
@@ -2083,7 +2083,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
 * this function must be called before setting the new value of
 * this function must be called before setting the new value of
 * rx_itr_setting
 * rx_itr_setting
 */
 */
static void ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
                               struct ethtool_coalesce *ec)
                               struct ethtool_coalesce *ec)
{
{
	/* check the old value and enable RSC if necessary */
	/* check the old value and enable RSC if necessary */
@@ -2093,11 +2093,9 @@ static void ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
		adapter->netdev->features |= NETIF_F_LRO;
		adapter->netdev->features |= NETIF_F_LRO;
		DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
		DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
		        ec->rx_coalesce_usecs);
		        ec->rx_coalesce_usecs);
		if (netif_running(adapter->netdev))
		return true;
			ixgbe_reinit_locked(adapter);
		else
			ixgbe_reset(adapter);
	}
	}
	return false;
}
}


static int ixgbe_set_coalesce(struct net_device *netdev,
static int ixgbe_set_coalesce(struct net_device *netdev,
@@ -2106,6 +2104,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
	struct ixgbe_q_vector *q_vector;
	struct ixgbe_q_vector *q_vector;
	int i;
	int i;
	bool need_reset = false;


	/* don't accept tx specific changes if we've got mixed RxTx vectors */
	/* don't accept tx specific changes if we've got mixed RxTx vectors */
	if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count
	if (adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count
@@ -2128,7 +2127,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
			return -EINVAL;
			return -EINVAL;


		/* check the old value and enable RSC if necessary */
		/* check the old value and enable RSC if necessary */
		ixgbe_reenable_rsc(adapter, ec);
		need_reset = ixgbe_reenable_rsc(adapter, ec);


		/* store the value in ints/second */
		/* store the value in ints/second */
		adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
		adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
@@ -2139,7 +2138,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
		adapter->rx_itr_setting &= ~1;
		adapter->rx_itr_setting &= ~1;
	} else if (ec->rx_coalesce_usecs == 1) {
	} else if (ec->rx_coalesce_usecs == 1) {
		/* check the old value and enable RSC if necessary */
		/* check the old value and enable RSC if necessary */
		ixgbe_reenable_rsc(adapter, ec);
		need_reset = ixgbe_reenable_rsc(adapter, ec);


		/* 1 means dynamic mode */
		/* 1 means dynamic mode */
		adapter->rx_eitr_param = 20000;
		adapter->rx_eitr_param = 20000;
@@ -2164,11 +2163,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
			DPRINTK(PROBE, INFO,
			DPRINTK(PROBE, INFO,
			        "rx-usecs set to 0, disabling RSC\n");
			        "rx-usecs set to 0, disabling RSC\n");


			if (netif_running(netdev))
			need_reset = true;
				ixgbe_reinit_locked(adapter);
			else
				ixgbe_reset(adapter);
			return 0;
		}
		}
	}
	}


@@ -2220,6 +2215,18 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
		ixgbe_write_eitr(q_vector);
		ixgbe_write_eitr(q_vector);
	}
	}


	/*
	 * do reset here at the end to make sure EITR==0 case is handled
	 * correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings
	 * also locks in RSC enable/disable which requires reset
	 */
	if (need_reset) {
		if (netif_running(netdev))
			ixgbe_reinit_locked(adapter);
		else
			ixgbe_reset(adapter);
	}

	return 0;
	return 0;
}
}


+7 −2
Original line number Original line Diff line number Diff line
@@ -2945,8 +2945,13 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
	for (i = 0; i < adapter->num_tx_queues; i++) {
	for (i = 0; i < adapter->num_tx_queues; i++) {
		j = adapter->tx_ring[i]->reg_idx;
		j = adapter->tx_ring[i]->reg_idx;
		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
		if (adapter->rx_itr_setting == 0) {
			/* cannot set wthresh when itr==0 */
			txdctl &= ~0x007F0000;
		} else {
			/* enable WTHRESH=8 descriptors, to encourage burst writeback */
			/* enable WTHRESH=8 descriptors, to encourage burst writeback */
			txdctl |= (8 << 16);
			txdctl |= (8 << 16);
		}
		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
	}
	}