diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 8bf11ca..f684be9 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8229,9 +8229,18 @@ void tg3_rss_init_indir_tbl(struct tg3 *tp)
 
 	if (tp->irq_cnt <= 2)
 		memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl));
-	else
+	else if (tg3_flag(tp, USER_INDIR_TBL)) {
+		/* Validate table against current IRQ count */
+		for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
+			if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1) {
+				/* Cap the vector index */
+				tp->rss_ind_tbl[i] = tp->irq_cnt - 2;
+			}
+		}
+	} else {
 		for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
 			tp->rss_ind_tbl[i] = i % (tp->irq_cnt - 1);
+	}
 }
 
 void tg3_rss_write_indir_tbl(struct tg3 *tp)
@@ -10719,6 +10728,120 @@ static int tg3_get_sset_count(struct net_device *dev, int sset)
 	}
 }
 
+static int tg3_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
+			 u32 *rules __always_unused)
+{
+	struct tg3 *tp = netdev_priv(dev);
+
+	if (!tg3_flag(tp, SUPPORT_MSIX))
+		return -EINVAL;
+
+	if (!netif_running(tp->dev))
+		return -EAGAIN;
+
+	switch (info->cmd) {
+	case ETHTOOL_GRXRINGS:
+		if (netif_running(tp->dev))
+			info->data = tp->irq_cnt;
+		else {
+			info->data = num_online_cpus();
+			if (info->data > TG3_IRQ_MAX_VECS_RSS)
+				info->data = TG3_IRQ_MAX_VECS_RSS;
+		}
+
+		/* The first interrupt vector only
+		 * handles link interrupts.
+		 */
+		info->data -= 1;
+		return 0;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int tg3_get_rxfh_indir(struct net_device *dev,
+			      struct ethtool_rxfh_indir *indir)
+{
+	struct tg3 *tp = netdev_priv(dev);
+	int i;
+
+	if (!tg3_flag(tp, SUPPORT_MSIX))
+		return -EINVAL;
+
+	if (!indir->size) {
+		indir->size = TG3_RSS_INDIR_TBL_SIZE;
+		return 0;
+	}
+
+	if (indir->size != TG3_RSS_INDIR_TBL_SIZE)
+		return -EINVAL;
+
+	for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
+		indir->ring_index[i] = tp->rss_ind_tbl[i];
+
+	return 0;
+}
+
+static int tg3_set_rxfh_indir(struct net_device *dev,
+			      const struct ethtool_rxfh_indir *indir)
+{
+	struct tg3 *tp = netdev_priv(dev);
+	size_t i;
+
+	if (!tg3_flag(tp, SUPPORT_MSIX))
+		return -EINVAL;
+
+	if (!indir->size) {
+		tg3_flag_clear(tp, USER_INDIR_TBL);
+		tg3_rss_init_indir_tbl(tp);
+	} else {
+		int limit;
+
+		/* Validate size and indices */
+		if (indir->size != TG3_RSS_INDIR_TBL_SIZE)
+			return -EINVAL;
+
+		if (netif_running(dev))
+			limit = tp->irq_cnt;
+		else {
+			limit = num_online_cpus();
+			if (limit > TG3_IRQ_MAX_VECS_RSS)
+				limit = TG3_IRQ_MAX_VECS_RSS;
+		}
+
+		/* The first interrupt vector only
+		 * handles link interrupts.
+		 */
+		limit -= 1;
+
+		/* Check the indices in the table.
+		 * Leave the existing table unmodified
+		 * if an error is detected.
+		 */
+		for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
+			if (indir->ring_index[i] >= limit)
+				return -EINVAL;
+
+		tg3_flag_set(tp, USER_INDIR_TBL);
+
+		for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
+			tp->rss_ind_tbl[i] = indir->ring_index[i];
+	}
+
+	if (!netif_running(dev) || !tg3_flag(tp, ENABLE_RSS))
+		return 0;
+
+	/* It is legal to write the indirection
+	 * table while the device is running.
+	 */
+	tg3_full_lock(tp, 0);
+	tg3_rss_write_indir_tbl(tp);
+	tg3_full_unlock(tp);
+
+	return 0;
+}
+
 static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
 {
 	switch (stringset) {
@@ -11949,6 +12072,9 @@ static const struct ethtool_ops tg3_ethtool_ops = {
 	.get_coalesce		= tg3_get_coalesce,
 	.set_coalesce		= tg3_set_coalesce,
 	.get_sset_count		= tg3_get_sset_count,
+	.get_rxnfc		= tg3_get_rxnfc,
+	.get_rxfh_indir		= tg3_get_rxfh_indir,
+	.set_rxfh_indir		= tg3_set_rxfh_indir,
 };
 
 static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index aea8f72..4800595 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2932,6 +2932,7 @@ enum TG3_FLAGS {
 	TG3_FLAG_APE_HAS_NCSI,
 	TG3_FLAG_4K_FIFO_LIMIT,
 	TG3_FLAG_RESET_TASK_PENDING,
+	TG3_FLAG_USER_INDIR_TBL,
 	TG3_FLAG_5705_PLUS,
 	TG3_FLAG_IS_5788,
 	TG3_FLAG_5750_PLUS,
