int i, rc;
        struct msix_entry msix_ent[tp->irq_max];
 
-       tp->rxq_cnt = netif_get_num_default_rss_queues();
+       tp->txq_cnt = tp->txq_req;
+       tp->rxq_cnt = tp->rxq_req;
+       if (!tp->rxq_cnt)
+               tp->rxq_cnt = netif_get_num_default_rss_queues();
        if (tp->rxq_cnt > tp->rxq_max)
                tp->rxq_cnt = tp->rxq_max;
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) &&
+           !tp->txq_req)
                tp->txq_cnt = min(tp->rxq_cnt, tp->txq_max);
 
        tp->irq_cnt = tg3_irq_count(tp);
        return 0;
 }
 
+static void tg3_get_channels(struct net_device *dev,
+                            struct ethtool_channels *channel)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       u32 deflt_qs = netif_get_num_default_rss_queues();
+
+       channel->max_rx = tp->rxq_max;
+       channel->max_tx = tp->txq_max;
+
+       if (netif_running(dev)) {
+               channel->rx_count = tp->rxq_cnt;
+               channel->tx_count = tp->txq_cnt;
+       } else {
+               if (tp->rxq_req)
+                       channel->rx_count = tp->rxq_req;
+               else
+                       channel->rx_count = min(deflt_qs, tp->rxq_max);
+
+               if (tp->txq_req)
+                       channel->tx_count = tp->txq_req;
+               else
+                       channel->tx_count = min(deflt_qs, tp->txq_max);
+       }
+}
+
+static int tg3_set_channels(struct net_device *dev,
+                           struct ethtool_channels *channel)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       if (!tg3_flag(tp, SUPPORT_MSIX))
+               return -EOPNOTSUPP;
+
+       if (channel->rx_count > tp->rxq_max ||
+           channel->tx_count > tp->txq_max)
+               return -EINVAL;
+
+       tp->rxq_req = channel->rx_count;
+       tp->txq_req = channel->tx_count;
+
+       if (!netif_running(dev))
+               return 0;
+
+       tg3_stop(tp);
+
+       netif_carrier_off(dev);
+
+       tg3_start(tp, true, false);
+
+       return 0;
+}
+
 static void tg3_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
 {
        switch (stringset) {
        .get_rxfh_indir_size    = tg3_get_rxfh_indir_size,
        .get_rxfh_indir         = tg3_get_rxfh_indir,
        .set_rxfh_indir         = tg3_set_rxfh_indir,
+       .get_channels           = tg3_get_channels,
+       .set_channels           = tg3_set_channels,
        .get_ts_info            = ethtool_op_get_ts_info,
 };