aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2009-02-12 09:07:09 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-16 02:43:54 -0500
commit3e5080344e95c0861a7ca494288593023ee383c6 (patch)
tree7660366975710f3577a0e9a110de9fc84178f925 /drivers/net/mv643xx_eth.c
parent6bdf576e4b068e86381280c58393cad42ffc8cc8 (diff)
mv643xx_eth: rework interrupt coalescing, and export via ethtool
This patch: - increases the precision of the receive/transmit interrupt coalescing register value computations by using 64bit temporaries; - adds functions to read the current hardware coalescing register values and convert them back to usecs; - exports the {get,set} {rx,tx} coal methods via the standard ethtool coalescing interface. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r--drivers/net/mv643xx_eth.c133
1 files changed, 103 insertions, 30 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index e8fbc0badf7..c32d623061d 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1221,6 +1221,85 @@ static void mib_counters_timer_wrapper(unsigned long _mp)
1221} 1221}
1222 1222
1223 1223
1224/* interrupt coalescing *****************************************************/
1225/*
1226 * Hardware coalescing parameters are set in units of 64 t_clk
1227 * cycles. I.e.:
1228 *
1229 * coal_delay_in_usec = 64000000 * register_value / t_clk_rate
1230 *
1231 * register_value = coal_delay_in_usec * t_clk_rate / 64000000
1232 *
1233 * In the ->set*() methods, we round the computed register value
1234 * to the nearest integer.
1235 */
1236static unsigned int get_rx_coal(struct mv643xx_eth_private *mp)
1237{
1238 u32 val = rdlp(mp, SDMA_CONFIG);
1239 u64 temp;
1240
1241 if (mp->shared->extended_rx_coal_limit)
1242 temp = ((val & 0x02000000) >> 10) | ((val & 0x003fff80) >> 7);
1243 else
1244 temp = (val & 0x003fff00) >> 8;
1245
1246 temp *= 64000000;
1247 do_div(temp, mp->shared->t_clk);
1248
1249 return (unsigned int)temp;
1250}
1251
1252static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int usec)
1253{
1254 u64 temp;
1255 u32 val;
1256
1257 temp = (u64)usec * mp->shared->t_clk;
1258 temp += 31999999;
1259 do_div(temp, 64000000);
1260
1261 val = rdlp(mp, SDMA_CONFIG);
1262 if (mp->shared->extended_rx_coal_limit) {
1263 if (temp > 0xffff)
1264 temp = 0xffff;
1265 val &= ~0x023fff80;
1266 val |= (temp & 0x8000) << 10;
1267 val |= (temp & 0x7fff) << 7;
1268 } else {
1269 if (temp > 0x3fff)
1270 temp = 0x3fff;
1271 val &= ~0x003fff00;
1272 val |= (temp & 0x3fff) << 8;
1273 }
1274 wrlp(mp, SDMA_CONFIG, val);
1275}
1276
1277static unsigned int get_tx_coal(struct mv643xx_eth_private *mp)
1278{
1279 u64 temp;
1280
1281 temp = (rdlp(mp, TX_FIFO_URGENT_THRESHOLD) & 0x3fff0) >> 4;
1282 temp *= 64000000;
1283 do_div(temp, mp->shared->t_clk);
1284
1285 return (unsigned int)temp;
1286}
1287
1288static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int usec)
1289{
1290 u64 temp;
1291
1292 temp = (u64)usec * mp->shared->t_clk;
1293 temp += 31999999;
1294 do_div(temp, 64000000);
1295
1296 if (temp > 0x3fff)
1297 temp = 0x3fff;
1298
1299 wrlp(mp, TX_FIFO_URGENT_THRESHOLD, temp << 4);
1300}
1301
1302
1224/* ethtool ******************************************************************/ 1303/* ethtool ******************************************************************/
1225struct mv643xx_eth_stats { 1304struct mv643xx_eth_stats {
1226 char stat_string[ETH_GSTRING_LEN]; 1305 char stat_string[ETH_GSTRING_LEN];
@@ -1384,6 +1463,28 @@ static u32 mv643xx_eth_get_link(struct net_device *dev)
1384 return !!netif_carrier_ok(dev); 1463 return !!netif_carrier_ok(dev);
1385} 1464}
1386 1465
1466static int
1467mv643xx_eth_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
1468{
1469 struct mv643xx_eth_private *mp = netdev_priv(dev);
1470
1471 ec->rx_coalesce_usecs = get_rx_coal(mp);
1472 ec->tx_coalesce_usecs = get_tx_coal(mp);
1473
1474 return 0;
1475}
1476
1477static int
1478mv643xx_eth_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
1479{
1480 struct mv643xx_eth_private *mp = netdev_priv(dev);
1481
1482 set_rx_coal(mp, ec->rx_coalesce_usecs);
1483 set_tx_coal(mp, ec->tx_coalesce_usecs);
1484
1485 return 0;
1486}
1487
1387static void mv643xx_eth_get_strings(struct net_device *dev, 1488static void mv643xx_eth_get_strings(struct net_device *dev,
1388 uint32_t stringset, uint8_t *data) 1489 uint32_t stringset, uint8_t *data)
1389{ 1490{
@@ -1438,6 +1539,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
1438 .get_drvinfo = mv643xx_eth_get_drvinfo, 1539 .get_drvinfo = mv643xx_eth_get_drvinfo,
1439 .nway_reset = mv643xx_eth_nway_reset, 1540 .nway_reset = mv643xx_eth_nway_reset,
1440 .get_link = mv643xx_eth_get_link, 1541 .get_link = mv643xx_eth_get_link,
1542 .get_coalesce = mv643xx_eth_get_coalesce,
1543 .set_coalesce = mv643xx_eth_set_coalesce,
1441 .set_sg = ethtool_op_set_sg, 1544 .set_sg = ethtool_op_set_sg,
1442 .get_strings = mv643xx_eth_get_strings, 1545 .get_strings = mv643xx_eth_get_strings,
1443 .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, 1546 .get_ethtool_stats = mv643xx_eth_get_ethtool_stats,
@@ -2053,36 +2156,6 @@ static void port_start(struct mv643xx_eth_private *mp)
2053 } 2156 }
2054} 2157}
2055 2158
2056static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
2057{
2058 unsigned int coal = ((mp->shared->t_clk / 1000000) * delay) / 64;
2059 u32 val;
2060
2061 val = rdlp(mp, SDMA_CONFIG);
2062 if (mp->shared->extended_rx_coal_limit) {
2063 if (coal > 0xffff)
2064 coal = 0xffff;
2065 val &= ~0x023fff80;
2066 val |= (coal & 0x8000) << 10;
2067 val |= (coal & 0x7fff) << 7;
2068 } else {
2069 if (coal > 0x3fff)
2070 coal = 0x3fff;
2071 val &= ~0x003fff00;
2072 val |= (coal & 0x3fff) << 8;
2073 }
2074 wrlp(mp, SDMA_CONFIG, val);
2075}
2076
2077static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
2078{
2079 unsigned int coal = ((mp->shared->t_clk / 1000000) * delay) / 64;
2080
2081 if (coal > 0x3fff)
2082 coal = 0x3fff;
2083 wrlp(mp, TX_FIFO_URGENT_THRESHOLD, (coal & 0x3fff) << 4);
2084}
2085
2086static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) 2159static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp)
2087{ 2160{
2088 int skb_size; 2161 int skb_size;