dev_kfree_skb_any(new_skb);
 }
 
-/* split budget depending on channel rates */
-static void cpsw_split_budget(struct net_device *ndev)
+static void cpsw_split_res(struct net_device *ndev)
 {
        struct cpsw_priv *priv = netdev_priv(ndev);
+       u32 consumed_rate = 0, bigest_rate = 0;
        struct cpsw_common *cpsw = priv->cpsw;
        struct cpsw_vector *txv = cpsw->txv;
-       u32 consumed_rate, bigest_rate = 0;
+       int i, ch_weight, rlim_ch_num = 0;
        int budget, bigest_rate_ch = 0;
        struct cpsw_slave *slave;
-       int i, rlim_ch_num = 0;
        u32 ch_rate, max_rate;
        int ch_budget = 0;
 
-       if (cpsw->data.dual_emac)
-               slave = &cpsw->slaves[priv->emac_port];
-       else
-               slave = &cpsw->slaves[cpsw->data.active_slave];
-
-       max_rate = slave->phy->speed * 1000;
-
-       consumed_rate = 0;
        for (i = 0; i < cpsw->tx_ch_num; i++) {
                ch_rate = cpdma_chan_get_rate(txv[i].ch);
                if (!ch_rate)
 
        if (cpsw->tx_ch_num == rlim_ch_num) {
                max_rate = consumed_rate;
+       } else if (!rlim_ch_num) {
+               ch_budget = CPSW_POLL_WEIGHT / cpsw->tx_ch_num;
+               bigest_rate = 0;
+               max_rate = consumed_rate;
        } else {
+               slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)];
+               max_rate = slave->phy->speed * 1000;
+
                ch_budget = (consumed_rate * CPSW_POLL_WEIGHT) / max_rate;
                ch_budget = (CPSW_POLL_WEIGHT - ch_budget) /
                            (cpsw->tx_ch_num - rlim_ch_num);
                              (cpsw->tx_ch_num - rlim_ch_num);
        }
 
-       /* split tx budget */
+       /* split tx weight/budget */
        budget = CPSW_POLL_WEIGHT;
        for (i = 0; i < cpsw->tx_ch_num; i++) {
                ch_rate = cpdma_chan_get_rate(txv[i].ch);
                if (ch_rate) {
                        txv[i].budget = (ch_rate * CPSW_POLL_WEIGHT) / max_rate;
                        if (!txv[i].budget)
-                               txv[i].budget = 1;
+                               txv[i].budget++;
                        if (ch_rate > bigest_rate) {
                                bigest_rate_ch = i;
                                bigest_rate = ch_rate;
                        }
+
+                       ch_weight = (ch_rate * 100) / max_rate;
+                       if (!ch_weight)
+                               ch_weight++;
+                       cpdma_chan_set_weight(cpsw->txv[i].ch, ch_weight);
                } else {
                        txv[i].budget = ch_budget;
                        if (!bigest_rate_ch)
                                bigest_rate_ch = i;
+                       cpdma_chan_set_weight(cpsw->txv[i].ch, 0);
                }
 
                budget -= txv[i].budget;
        for_each_slave(priv, _cpsw_adjust_link, priv, &link);
 
        if (link) {
-               cpsw_split_budget(priv->ndev);
+               cpsw_split_res(priv->ndev);
                netif_carrier_on(ndev);
                if (netif_running(ndev))
                        netif_tx_wake_all_queues(ndev);
 static int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate)
 {
        struct cpsw_priv *priv = netdev_priv(ndev);
-       int tx_ch_num = ndev->real_num_tx_queues;
-       u32 consumed_rate, min_rate, max_rate;
        struct cpsw_common *cpsw = priv->cpsw;
-       struct cpsw_slave *slave;
-       int ret, i, weight;
-       int rlim_num = 0;
+       u32 min_rate;
        u32 ch_rate;
+       int ret;
 
        ch_rate = netdev_get_tx_queue(ndev, queue)->tx_maxrate;
        if (ch_rate == rate)
                return 0;
 
-       if (cpsw->data.dual_emac)
-               slave = &cpsw->slaves[priv->emac_port];
-       else
-               slave = &cpsw->slaves[cpsw->data.active_slave];
-       max_rate = slave->phy->speed;
-
-       consumed_rate = 0;
-       for (i = 0; i < tx_ch_num; i++) {
-               if (i == queue)
-                       ch_rate = rate;
-               else
-                       ch_rate = netdev_get_tx_queue(ndev, i)->tx_maxrate;
-               if (!ch_rate)
-                       continue;
-
-               rlim_num++;
-               consumed_rate += ch_rate;
-       }
-
-       if (consumed_rate > max_rate)
-               dev_info(priv->dev, "The common rate shouldn't be more than %dMbps",
-                        max_rate);
-
-       if (consumed_rate > max_rate) {
-               if (max_rate == 10 && consumed_rate <= 100) {
-                       max_rate = 100;
-               } else if (max_rate <= 100 && consumed_rate <= 1000) {
-                       max_rate = 1000;
-               } else {
-                       dev_err(priv->dev, "The common rate cannot be more than %dMbps",
-                               max_rate);
-                       return -EINVAL;
-               }
-       }
-
-       if (consumed_rate > max_rate) {
-               dev_err(priv->dev, "The common rate cannot be more than %dMbps",
-                       max_rate);
+       ch_rate = rate * 1000;
+       min_rate = cpdma_chan_get_min_rate(cpsw->dma);
+       if ((ch_rate < min_rate && ch_rate)) {
+               dev_err(priv->dev, "The channel rate cannot be less than %dMbps",
+                       min_rate);
                return -EINVAL;
        }
 
-       rate *= 1000;
-       min_rate = cpdma_chan_get_min_rate(cpsw->dma);
-       if ((rate < min_rate && rate)) {
-               dev_err(priv->dev, "The common rate cannot be less than %dMbps",
-                       min_rate);
+       if (rate > 2000) {
+               dev_err(priv->dev, "The channel rate cannot be more than 2Gbps");
                return -EINVAL;
        }
 
                return ret;
        }
 
-       if (rlim_num == tx_ch_num)
-               max_rate = consumed_rate;
+       ret = cpdma_chan_set_rate(cpsw->txv[queue].ch, ch_rate);
+       pm_runtime_put(cpsw->dev);
 
-       weight = (rate * 100) / (max_rate * 1000);
-       cpdma_chan_set_weight(cpsw->txv[queue].ch, weight);
-       ret = cpdma_chan_set_rate(cpsw->txv[queue].ch, rate);
+       if (ret)
+               return ret;
 
-       /* re-split budget between channels */
-       if (!rate)
-               cpsw_split_budget(ndev);
-       pm_runtime_put(cpsw->dev);
+       cpsw_split_res(ndev);
        return ret;
 }
 
                if (ret)
                        goto err;
 
-               cpsw_split_budget(ndev);
+               cpsw_split_res(ndev);
 
                /* After this receive is started */
                cpdma_ctlr_start(cpsw->dma);