.. | .. |
---|
1691 | 1691 | |
---|
1692 | 1692 | #define BYTES_PER_KBIT (1000LL / 8) |
---|
1693 | 1693 | |
---|
| 1694 | +static int sja1105_find_cbs_shaper(struct sja1105_private *priv, |
---|
| 1695 | + int port, int prio) |
---|
| 1696 | +{ |
---|
| 1697 | + int i; |
---|
| 1698 | + |
---|
| 1699 | + for (i = 0; i < priv->info->num_cbs_shapers; i++) |
---|
| 1700 | + if (priv->cbs[i].port == port && priv->cbs[i].prio == prio) |
---|
| 1701 | + return i; |
---|
| 1702 | + |
---|
| 1703 | + return -1; |
---|
| 1704 | +} |
---|
| 1705 | + |
---|
1694 | 1706 | static int sja1105_find_unused_cbs_shaper(struct sja1105_private *priv) |
---|
1695 | 1707 | { |
---|
1696 | 1708 | int i; |
---|
.. | .. |
---|
1725 | 1737 | { |
---|
1726 | 1738 | struct sja1105_private *priv = ds->priv; |
---|
1727 | 1739 | struct sja1105_cbs_entry *cbs; |
---|
| 1740 | + s64 port_transmit_rate_kbps; |
---|
1728 | 1741 | int index; |
---|
1729 | 1742 | |
---|
1730 | 1743 | if (!offload->enable) |
---|
1731 | 1744 | return sja1105_delete_cbs_shaper(priv, port, offload->queue); |
---|
1732 | 1745 | |
---|
1733 | | - index = sja1105_find_unused_cbs_shaper(priv); |
---|
1734 | | - if (index < 0) |
---|
1735 | | - return -ENOSPC; |
---|
| 1746 | + /* The user may be replacing an existing shaper */ |
---|
| 1747 | + index = sja1105_find_cbs_shaper(priv, port, offload->queue); |
---|
| 1748 | + if (index < 0) { |
---|
| 1749 | + /* That isn't the case - see if we can allocate a new one */ |
---|
| 1750 | + index = sja1105_find_unused_cbs_shaper(priv); |
---|
| 1751 | + if (index < 0) |
---|
| 1752 | + return -ENOSPC; |
---|
| 1753 | + } |
---|
1736 | 1754 | |
---|
1737 | 1755 | cbs = &priv->cbs[index]; |
---|
1738 | 1756 | cbs->port = port; |
---|
.. | .. |
---|
1742 | 1760 | */ |
---|
1743 | 1761 | cbs->credit_hi = offload->hicredit; |
---|
1744 | 1762 | cbs->credit_lo = abs(offload->locredit); |
---|
1745 | | - /* User space is in kbits/sec, hardware in bytes/sec */ |
---|
1746 | | - cbs->idle_slope = offload->idleslope * BYTES_PER_KBIT; |
---|
1747 | | - cbs->send_slope = abs(offload->sendslope * BYTES_PER_KBIT); |
---|
| 1763 | + /* User space is in kbits/sec, while the hardware in bytes/sec times |
---|
| 1764 | + * link speed. Since the given offload->sendslope is good only for the |
---|
| 1765 | + * current link speed anyway, and user space is likely to reprogram it |
---|
| 1766 | + * when that changes, don't even bother to track the port's link speed, |
---|
| 1767 | + * but deduce the port transmit rate from idleslope - sendslope. |
---|
| 1768 | + */ |
---|
| 1769 | + port_transmit_rate_kbps = offload->idleslope - offload->sendslope; |
---|
| 1770 | + cbs->idle_slope = div_s64(offload->idleslope * BYTES_PER_KBIT, |
---|
| 1771 | + port_transmit_rate_kbps); |
---|
| 1772 | + cbs->send_slope = div_s64(abs(offload->sendslope * BYTES_PER_KBIT), |
---|
| 1773 | + port_transmit_rate_kbps); |
---|
1748 | 1774 | /* Convert the negative values from 64-bit 2's complement |
---|
1749 | 1775 | * to 32-bit 2's complement (for the case of 0x80000000 whose |
---|
1750 | 1776 | * negative is still negative). |
---|