mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-06 18:36:40 +07:00
net: ethernet: ti: cpsw: fix early budget split
The budget split function requires the phy speed to be known.
While ndo open a phy speed identification is postponed till the
moment link is up. Hence, move it to appropriate callback, when link
is up.
Reported-by: Grygorii Strashko <grygorii.strashko@ti.com>
Fixes: 8feb0a1965
("net: ethernet: ti: cpsw: split tx budget according between channels")
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
343dfaa198
commit
48e0a83ece
@ -753,6 +753,82 @@ static void cpsw_rx_handler(void *token, int len, int status)
|
||||
dev_kfree_skb_any(new_skb);
|
||||
}
|
||||
|
||||
/* split budget depending on channel rates */
|
||||
static void cpsw_split_budget(struct net_device *ndev)
|
||||
{
|
||||
struct cpsw_priv *priv = netdev_priv(ndev);
|
||||
struct cpsw_common *cpsw = priv->cpsw;
|
||||
struct cpsw_vector *txv = cpsw->txv;
|
||||
u32 consumed_rate, bigest_rate = 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)
|
||||
continue;
|
||||
|
||||
rlim_ch_num++;
|
||||
consumed_rate += ch_rate;
|
||||
}
|
||||
|
||||
if (cpsw->tx_ch_num == rlim_ch_num) {
|
||||
max_rate = consumed_rate;
|
||||
} else {
|
||||
ch_budget = (consumed_rate * CPSW_POLL_WEIGHT) / max_rate;
|
||||
ch_budget = (CPSW_POLL_WEIGHT - ch_budget) /
|
||||
(cpsw->tx_ch_num - rlim_ch_num);
|
||||
bigest_rate = (max_rate - consumed_rate) /
|
||||
(cpsw->tx_ch_num - rlim_ch_num);
|
||||
}
|
||||
|
||||
/* split tx 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;
|
||||
if (ch_rate > bigest_rate) {
|
||||
bigest_rate_ch = i;
|
||||
bigest_rate = ch_rate;
|
||||
}
|
||||
} else {
|
||||
txv[i].budget = ch_budget;
|
||||
if (!bigest_rate_ch)
|
||||
bigest_rate_ch = i;
|
||||
}
|
||||
|
||||
budget -= txv[i].budget;
|
||||
}
|
||||
|
||||
if (budget)
|
||||
txv[bigest_rate_ch].budget += budget;
|
||||
|
||||
/* split rx budget */
|
||||
budget = CPSW_POLL_WEIGHT;
|
||||
ch_budget = budget / cpsw->rx_ch_num;
|
||||
for (i = 0; i < cpsw->rx_ch_num; i++) {
|
||||
cpsw->rxv[i].budget = ch_budget;
|
||||
budget -= ch_budget;
|
||||
}
|
||||
|
||||
if (budget)
|
||||
cpsw->rxv[0].budget += budget;
|
||||
}
|
||||
|
||||
static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct cpsw_common *cpsw = dev_id;
|
||||
@ -941,6 +1017,7 @@ static void cpsw_adjust_link(struct net_device *ndev)
|
||||
for_each_slave(priv, _cpsw_adjust_link, priv, &link);
|
||||
|
||||
if (link) {
|
||||
cpsw_split_budget(priv->ndev);
|
||||
netif_carrier_on(ndev);
|
||||
if (netif_running(ndev))
|
||||
netif_tx_wake_all_queues(ndev);
|
||||
@ -1280,82 +1357,6 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
|
||||
}
|
||||
}
|
||||
|
||||
/* split budget depending on channel rates */
|
||||
static void cpsw_split_budget(struct net_device *ndev)
|
||||
{
|
||||
struct cpsw_priv *priv = netdev_priv(ndev);
|
||||
struct cpsw_common *cpsw = priv->cpsw;
|
||||
struct cpsw_vector *txv = cpsw->txv;
|
||||
u32 consumed_rate, bigest_rate = 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)
|
||||
continue;
|
||||
|
||||
rlim_ch_num++;
|
||||
consumed_rate += ch_rate;
|
||||
}
|
||||
|
||||
if (cpsw->tx_ch_num == rlim_ch_num) {
|
||||
max_rate = consumed_rate;
|
||||
} else {
|
||||
ch_budget = (consumed_rate * CPSW_POLL_WEIGHT) / max_rate;
|
||||
ch_budget = (CPSW_POLL_WEIGHT - ch_budget) /
|
||||
(cpsw->tx_ch_num - rlim_ch_num);
|
||||
bigest_rate = (max_rate - consumed_rate) /
|
||||
(cpsw->tx_ch_num - rlim_ch_num);
|
||||
}
|
||||
|
||||
/* split tx 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;
|
||||
if (ch_rate > bigest_rate) {
|
||||
bigest_rate_ch = i;
|
||||
bigest_rate = ch_rate;
|
||||
}
|
||||
} else {
|
||||
txv[i].budget = ch_budget;
|
||||
if (!bigest_rate_ch)
|
||||
bigest_rate_ch = i;
|
||||
}
|
||||
|
||||
budget -= txv[i].budget;
|
||||
}
|
||||
|
||||
if (budget)
|
||||
txv[bigest_rate_ch].budget += budget;
|
||||
|
||||
/* split rx budget */
|
||||
budget = CPSW_POLL_WEIGHT;
|
||||
ch_budget = budget / cpsw->rx_ch_num;
|
||||
for (i = 0; i < cpsw->rx_ch_num; i++) {
|
||||
cpsw->rxv[i].budget = ch_budget;
|
||||
budget -= ch_budget;
|
||||
}
|
||||
|
||||
if (budget)
|
||||
cpsw->rxv[0].budget += budget;
|
||||
}
|
||||
|
||||
static int cpsw_fill_rx_channels(struct cpsw_priv *priv)
|
||||
{
|
||||
struct cpsw_common *cpsw = priv->cpsw;
|
||||
@ -1501,7 +1502,6 @@ static int cpsw_ndo_open(struct net_device *ndev)
|
||||
cpsw_set_coalesce(ndev, &coal);
|
||||
}
|
||||
|
||||
cpsw_split_budget(ndev);
|
||||
cpdma_ctlr_start(cpsw->dma);
|
||||
cpsw_intr_enable(cpsw);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user