diff options
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 412 |
1 files changed, 322 insertions, 90 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b0bc3bc18e9c..a56d9d2df73f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/mv643xx_eth.h> | 53 | #include <linux/mv643xx_eth.h> |
54 | #include <linux/io.h> | 54 | #include <linux/io.h> |
55 | #include <linux/types.h> | 55 | #include <linux/types.h> |
56 | #include <linux/inet_lro.h> | ||
56 | #include <asm/system.h> | 57 | #include <asm/system.h> |
57 | 58 | ||
58 | static char mv643xx_eth_driver_name[] = "mv643xx_eth"; | 59 | static char mv643xx_eth_driver_name[] = "mv643xx_eth"; |
@@ -227,6 +228,12 @@ struct tx_desc { | |||
227 | #define RX_ENABLE_INTERRUPT 0x20000000 | 228 | #define RX_ENABLE_INTERRUPT 0x20000000 |
228 | #define RX_FIRST_DESC 0x08000000 | 229 | #define RX_FIRST_DESC 0x08000000 |
229 | #define RX_LAST_DESC 0x04000000 | 230 | #define RX_LAST_DESC 0x04000000 |
231 | #define RX_IP_HDR_OK 0x02000000 | ||
232 | #define RX_PKT_IS_IPV4 0x01000000 | ||
233 | #define RX_PKT_IS_ETHERNETV2 0x00800000 | ||
234 | #define RX_PKT_LAYER4_TYPE_MASK 0x00600000 | ||
235 | #define RX_PKT_LAYER4_TYPE_TCP_IPV4 0x00000000 | ||
236 | #define RX_PKT_IS_VLAN_TAGGED 0x00080000 | ||
230 | 237 | ||
231 | /* TX descriptor command */ | 238 | /* TX descriptor command */ |
232 | #define TX_ENABLE_INTERRUPT 0x00800000 | 239 | #define TX_ENABLE_INTERRUPT 0x00800000 |
@@ -286,6 +293,9 @@ struct mv643xx_eth_shared_private { | |||
286 | #define TX_BW_CONTROL_OLD_LAYOUT 1 | 293 | #define TX_BW_CONTROL_OLD_LAYOUT 1 |
287 | #define TX_BW_CONTROL_NEW_LAYOUT 2 | 294 | #define TX_BW_CONTROL_NEW_LAYOUT 2 |
288 | 295 | ||
296 | static int mv643xx_eth_open(struct net_device *dev); | ||
297 | static int mv643xx_eth_stop(struct net_device *dev); | ||
298 | |||
289 | 299 | ||
290 | /* per-port *****************************************************************/ | 300 | /* per-port *****************************************************************/ |
291 | struct mib_counters { | 301 | struct mib_counters { |
@@ -321,6 +331,12 @@ struct mib_counters { | |||
321 | u32 late_collision; | 331 | u32 late_collision; |
322 | }; | 332 | }; |
323 | 333 | ||
334 | struct lro_counters { | ||
335 | u32 lro_aggregated; | ||
336 | u32 lro_flushed; | ||
337 | u32 lro_no_desc; | ||
338 | }; | ||
339 | |||
324 | struct rx_queue { | 340 | struct rx_queue { |
325 | int index; | 341 | int index; |
326 | 342 | ||
@@ -334,6 +350,9 @@ struct rx_queue { | |||
334 | dma_addr_t rx_desc_dma; | 350 | dma_addr_t rx_desc_dma; |
335 | int rx_desc_area_size; | 351 | int rx_desc_area_size; |
336 | struct sk_buff **rx_skb; | 352 | struct sk_buff **rx_skb; |
353 | |||
354 | struct net_lro_mgr lro_mgr; | ||
355 | struct net_lro_desc lro_arr[8]; | ||
337 | }; | 356 | }; |
338 | 357 | ||
339 | struct tx_queue { | 358 | struct tx_queue { |
@@ -369,6 +388,8 @@ struct mv643xx_eth_private { | |||
369 | spinlock_t mib_counters_lock; | 388 | spinlock_t mib_counters_lock; |
370 | struct mib_counters mib_counters; | 389 | struct mib_counters mib_counters; |
371 | 390 | ||
391 | struct lro_counters lro_counters; | ||
392 | |||
372 | struct work_struct tx_timeout_task; | 393 | struct work_struct tx_timeout_task; |
373 | 394 | ||
374 | struct napi_struct napi; | 395 | struct napi_struct napi; |
@@ -385,7 +406,7 @@ struct mv643xx_eth_private { | |||
385 | /* | 406 | /* |
386 | * RX state. | 407 | * RX state. |
387 | */ | 408 | */ |
388 | int default_rx_ring_size; | 409 | int rx_ring_size; |
389 | unsigned long rx_desc_sram_addr; | 410 | unsigned long rx_desc_sram_addr; |
390 | int rx_desc_sram_size; | 411 | int rx_desc_sram_size; |
391 | int rxq_count; | 412 | int rxq_count; |
@@ -395,7 +416,7 @@ struct mv643xx_eth_private { | |||
395 | /* | 416 | /* |
396 | * TX state. | 417 | * TX state. |
397 | */ | 418 | */ |
398 | int default_tx_ring_size; | 419 | int tx_ring_size; |
399 | unsigned long tx_desc_sram_addr; | 420 | unsigned long tx_desc_sram_addr; |
400 | int tx_desc_sram_size; | 421 | int tx_desc_sram_size; |
401 | int txq_count; | 422 | int txq_count; |
@@ -493,12 +514,40 @@ static void txq_maybe_wake(struct tx_queue *txq) | |||
493 | 514 | ||
494 | 515 | ||
495 | /* rx napi ******************************************************************/ | 516 | /* rx napi ******************************************************************/ |
517 | static int | ||
518 | mv643xx_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph, | ||
519 | u64 *hdr_flags, void *priv) | ||
520 | { | ||
521 | unsigned long cmd_sts = (unsigned long)priv; | ||
522 | |||
523 | /* | ||
524 | * Make sure that this packet is Ethernet II, is not VLAN | ||
525 | * tagged, is IPv4, has a valid IP header, and is TCP. | ||
526 | */ | ||
527 | if ((cmd_sts & (RX_IP_HDR_OK | RX_PKT_IS_IPV4 | | ||
528 | RX_PKT_IS_ETHERNETV2 | RX_PKT_LAYER4_TYPE_MASK | | ||
529 | RX_PKT_IS_VLAN_TAGGED)) != | ||
530 | (RX_IP_HDR_OK | RX_PKT_IS_IPV4 | | ||
531 | RX_PKT_IS_ETHERNETV2 | RX_PKT_LAYER4_TYPE_TCP_IPV4)) | ||
532 | return -1; | ||
533 | |||
534 | skb_reset_network_header(skb); | ||
535 | skb_set_transport_header(skb, ip_hdrlen(skb)); | ||
536 | *iphdr = ip_hdr(skb); | ||
537 | *tcph = tcp_hdr(skb); | ||
538 | *hdr_flags = LRO_IPV4 | LRO_TCP; | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
496 | static int rxq_process(struct rx_queue *rxq, int budget) | 543 | static int rxq_process(struct rx_queue *rxq, int budget) |
497 | { | 544 | { |
498 | struct mv643xx_eth_private *mp = rxq_to_mp(rxq); | 545 | struct mv643xx_eth_private *mp = rxq_to_mp(rxq); |
499 | struct net_device_stats *stats = &mp->dev->stats; | 546 | struct net_device_stats *stats = &mp->dev->stats; |
547 | int lro_flush_needed; | ||
500 | int rx; | 548 | int rx; |
501 | 549 | ||
550 | lro_flush_needed = 0; | ||
502 | rx = 0; | 551 | rx = 0; |
503 | while (rx < budget && rxq->rx_desc_count) { | 552 | while (rx < budget && rxq->rx_desc_count) { |
504 | struct rx_desc *rx_desc; | 553 | struct rx_desc *rx_desc; |
@@ -558,7 +607,13 @@ static int rxq_process(struct rx_queue *rxq, int budget) | |||
558 | if (cmd_sts & LAYER_4_CHECKSUM_OK) | 607 | if (cmd_sts & LAYER_4_CHECKSUM_OK) |
559 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 608 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
560 | skb->protocol = eth_type_trans(skb, mp->dev); | 609 | skb->protocol = eth_type_trans(skb, mp->dev); |
561 | netif_receive_skb(skb); | 610 | |
611 | if (skb->dev->features & NETIF_F_LRO && | ||
612 | skb->ip_summed == CHECKSUM_UNNECESSARY) { | ||
613 | lro_receive_skb(&rxq->lro_mgr, skb, (void *)cmd_sts); | ||
614 | lro_flush_needed = 1; | ||
615 | } else | ||
616 | netif_receive_skb(skb); | ||
562 | 617 | ||
563 | continue; | 618 | continue; |
564 | 619 | ||
@@ -579,6 +634,9 @@ err: | |||
579 | dev_kfree_skb(skb); | 634 | dev_kfree_skb(skb); |
580 | } | 635 | } |
581 | 636 | ||
637 | if (lro_flush_needed) | ||
638 | lro_flush_all(&rxq->lro_mgr); | ||
639 | |||
582 | if (rx < budget) | 640 | if (rx < budget) |
583 | mp->work_rx &= ~(1 << rxq->index); | 641 | mp->work_rx &= ~(1 << rxq->index); |
584 | 642 | ||
@@ -907,7 +965,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) | |||
907 | 965 | ||
908 | if (skb != NULL) { | 966 | if (skb != NULL) { |
909 | if (skb_queue_len(&mp->rx_recycle) < | 967 | if (skb_queue_len(&mp->rx_recycle) < |
910 | mp->default_rx_ring_size && | 968 | mp->rx_ring_size && |
911 | skb_recycle_check(skb, mp->skb_size + | 969 | skb_recycle_check(skb, mp->skb_size + |
912 | dma_get_cache_alignment() - 1)) | 970 | dma_get_cache_alignment() - 1)) |
913 | __skb_queue_head(&mp->rx_recycle, skb); | 971 | __skb_queue_head(&mp->rx_recycle, skb); |
@@ -1158,6 +1216,26 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev) | |||
1158 | return stats; | 1216 | return stats; |
1159 | } | 1217 | } |
1160 | 1218 | ||
1219 | static void mv643xx_eth_grab_lro_stats(struct mv643xx_eth_private *mp) | ||
1220 | { | ||
1221 | u32 lro_aggregated = 0; | ||
1222 | u32 lro_flushed = 0; | ||
1223 | u32 lro_no_desc = 0; | ||
1224 | int i; | ||
1225 | |||
1226 | for (i = 0; i < mp->rxq_count; i++) { | ||
1227 | struct rx_queue *rxq = mp->rxq + i; | ||
1228 | |||
1229 | lro_aggregated += rxq->lro_mgr.stats.aggregated; | ||
1230 | lro_flushed += rxq->lro_mgr.stats.flushed; | ||
1231 | lro_no_desc += rxq->lro_mgr.stats.no_desc; | ||
1232 | } | ||
1233 | |||
1234 | mp->lro_counters.lro_aggregated = lro_aggregated; | ||
1235 | mp->lro_counters.lro_flushed = lro_flushed; | ||
1236 | mp->lro_counters.lro_no_desc = lro_no_desc; | ||
1237 | } | ||
1238 | |||
1161 | static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset) | 1239 | static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset) |
1162 | { | 1240 | { |
1163 | return rdl(mp, MIB_COUNTERS(mp->port_num) + offset); | 1241 | return rdl(mp, MIB_COUNTERS(mp->port_num) + offset); |
@@ -1221,6 +1299,85 @@ static void mib_counters_timer_wrapper(unsigned long _mp) | |||
1221 | } | 1299 | } |
1222 | 1300 | ||
1223 | 1301 | ||
1302 | /* interrupt coalescing *****************************************************/ | ||
1303 | /* | ||
1304 | * Hardware coalescing parameters are set in units of 64 t_clk | ||
1305 | * cycles. I.e.: | ||
1306 | * | ||
1307 | * coal_delay_in_usec = 64000000 * register_value / t_clk_rate | ||
1308 | * | ||
1309 | * register_value = coal_delay_in_usec * t_clk_rate / 64000000 | ||
1310 | * | ||
1311 | * In the ->set*() methods, we round the computed register value | ||
1312 | * to the nearest integer. | ||
1313 | */ | ||
1314 | static unsigned int get_rx_coal(struct mv643xx_eth_private *mp) | ||
1315 | { | ||
1316 | u32 val = rdlp(mp, SDMA_CONFIG); | ||
1317 | u64 temp; | ||
1318 | |||
1319 | if (mp->shared->extended_rx_coal_limit) | ||
1320 | temp = ((val & 0x02000000) >> 10) | ((val & 0x003fff80) >> 7); | ||
1321 | else | ||
1322 | temp = (val & 0x003fff00) >> 8; | ||
1323 | |||
1324 | temp *= 64000000; | ||
1325 | do_div(temp, mp->shared->t_clk); | ||
1326 | |||
1327 | return (unsigned int)temp; | ||
1328 | } | ||
1329 | |||
1330 | static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int usec) | ||
1331 | { | ||
1332 | u64 temp; | ||
1333 | u32 val; | ||
1334 | |||
1335 | temp = (u64)usec * mp->shared->t_clk; | ||
1336 | temp += 31999999; | ||
1337 | do_div(temp, 64000000); | ||
1338 | |||
1339 | val = rdlp(mp, SDMA_CONFIG); | ||
1340 | if (mp->shared->extended_rx_coal_limit) { | ||
1341 | if (temp > 0xffff) | ||
1342 | temp = 0xffff; | ||
1343 | val &= ~0x023fff80; | ||
1344 | val |= (temp & 0x8000) << 10; | ||
1345 | val |= (temp & 0x7fff) << 7; | ||
1346 | } else { | ||
1347 | if (temp > 0x3fff) | ||
1348 | temp = 0x3fff; | ||
1349 | val &= ~0x003fff00; | ||
1350 | val |= (temp & 0x3fff) << 8; | ||
1351 | } | ||
1352 | wrlp(mp, SDMA_CONFIG, val); | ||
1353 | } | ||
1354 | |||
1355 | static unsigned int get_tx_coal(struct mv643xx_eth_private *mp) | ||
1356 | { | ||
1357 | u64 temp; | ||
1358 | |||
1359 | temp = (rdlp(mp, TX_FIFO_URGENT_THRESHOLD) & 0x3fff0) >> 4; | ||
1360 | temp *= 64000000; | ||
1361 | do_div(temp, mp->shared->t_clk); | ||
1362 | |||
1363 | return (unsigned int)temp; | ||
1364 | } | ||
1365 | |||
1366 | static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int usec) | ||
1367 | { | ||
1368 | u64 temp; | ||
1369 | |||
1370 | temp = (u64)usec * mp->shared->t_clk; | ||
1371 | temp += 31999999; | ||
1372 | do_div(temp, 64000000); | ||
1373 | |||
1374 | if (temp > 0x3fff) | ||
1375 | temp = 0x3fff; | ||
1376 | |||
1377 | wrlp(mp, TX_FIFO_URGENT_THRESHOLD, temp << 4); | ||
1378 | } | ||
1379 | |||
1380 | |||
1224 | /* ethtool ******************************************************************/ | 1381 | /* ethtool ******************************************************************/ |
1225 | struct mv643xx_eth_stats { | 1382 | struct mv643xx_eth_stats { |
1226 | char stat_string[ETH_GSTRING_LEN]; | 1383 | char stat_string[ETH_GSTRING_LEN]; |
@@ -1237,6 +1394,10 @@ struct mv643xx_eth_stats { | |||
1237 | { #m, FIELD_SIZEOF(struct mib_counters, m), \ | 1394 | { #m, FIELD_SIZEOF(struct mib_counters, m), \ |
1238 | -1, offsetof(struct mv643xx_eth_private, mib_counters.m) } | 1395 | -1, offsetof(struct mv643xx_eth_private, mib_counters.m) } |
1239 | 1396 | ||
1397 | #define LROSTAT(m) \ | ||
1398 | { #m, FIELD_SIZEOF(struct lro_counters, m), \ | ||
1399 | -1, offsetof(struct mv643xx_eth_private, lro_counters.m) } | ||
1400 | |||
1240 | static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { | 1401 | static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { |
1241 | SSTAT(rx_packets), | 1402 | SSTAT(rx_packets), |
1242 | SSTAT(tx_packets), | 1403 | SSTAT(tx_packets), |
@@ -1276,12 +1437,15 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { | |||
1276 | MIBSTAT(bad_crc_event), | 1437 | MIBSTAT(bad_crc_event), |
1277 | MIBSTAT(collision), | 1438 | MIBSTAT(collision), |
1278 | MIBSTAT(late_collision), | 1439 | MIBSTAT(late_collision), |
1440 | LROSTAT(lro_aggregated), | ||
1441 | LROSTAT(lro_flushed), | ||
1442 | LROSTAT(lro_no_desc), | ||
1279 | }; | 1443 | }; |
1280 | 1444 | ||
1281 | static int | 1445 | static int |
1282 | mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 1446 | mv643xx_eth_get_settings_phy(struct mv643xx_eth_private *mp, |
1447 | struct ethtool_cmd *cmd) | ||
1283 | { | 1448 | { |
1284 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1285 | int err; | 1449 | int err; |
1286 | 1450 | ||
1287 | err = phy_read_status(mp->phy); | 1451 | err = phy_read_status(mp->phy); |
@@ -1298,10 +1462,9 @@ mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1298 | } | 1462 | } |
1299 | 1463 | ||
1300 | static int | 1464 | static int |
1301 | mv643xx_eth_get_settings_phyless(struct net_device *dev, | 1465 | mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp, |
1302 | struct ethtool_cmd *cmd) | 1466 | struct ethtool_cmd *cmd) |
1303 | { | 1467 | { |
1304 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1305 | u32 port_status; | 1468 | u32 port_status; |
1306 | 1469 | ||
1307 | port_status = rdlp(mp, PORT_STATUS); | 1470 | port_status = rdlp(mp, PORT_STATUS); |
@@ -1334,10 +1497,24 @@ mv643xx_eth_get_settings_phyless(struct net_device *dev, | |||
1334 | } | 1497 | } |
1335 | 1498 | ||
1336 | static int | 1499 | static int |
1500 | mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
1501 | { | ||
1502 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1503 | |||
1504 | if (mp->phy != NULL) | ||
1505 | return mv643xx_eth_get_settings_phy(mp, cmd); | ||
1506 | else | ||
1507 | return mv643xx_eth_get_settings_phyless(mp, cmd); | ||
1508 | } | ||
1509 | |||
1510 | static int | ||
1337 | mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 1511 | mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
1338 | { | 1512 | { |
1339 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1513 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1340 | 1514 | ||
1515 | if (mp->phy == NULL) | ||
1516 | return -EINVAL; | ||
1517 | |||
1341 | /* | 1518 | /* |
1342 | * The MAC does not support 1000baseT_Half. | 1519 | * The MAC does not support 1000baseT_Half. |
1343 | */ | 1520 | */ |
@@ -1346,13 +1523,6 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1346 | return phy_ethtool_sset(mp->phy, cmd); | 1523 | return phy_ethtool_sset(mp->phy, cmd); |
1347 | } | 1524 | } |
1348 | 1525 | ||
1349 | static int | ||
1350 | mv643xx_eth_set_settings_phyless(struct net_device *dev, | ||
1351 | struct ethtool_cmd *cmd) | ||
1352 | { | ||
1353 | return -EINVAL; | ||
1354 | } | ||
1355 | |||
1356 | static void mv643xx_eth_get_drvinfo(struct net_device *dev, | 1526 | static void mv643xx_eth_get_drvinfo(struct net_device *dev, |
1357 | struct ethtool_drvinfo *drvinfo) | 1527 | struct ethtool_drvinfo *drvinfo) |
1358 | { | 1528 | { |
@@ -1367,17 +1537,95 @@ static int mv643xx_eth_nway_reset(struct net_device *dev) | |||
1367 | { | 1537 | { |
1368 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1538 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1369 | 1539 | ||
1540 | if (mp->phy == NULL) | ||
1541 | return -EINVAL; | ||
1542 | |||
1370 | return genphy_restart_aneg(mp->phy); | 1543 | return genphy_restart_aneg(mp->phy); |
1371 | } | 1544 | } |
1372 | 1545 | ||
1373 | static int mv643xx_eth_nway_reset_phyless(struct net_device *dev) | 1546 | static u32 mv643xx_eth_get_link(struct net_device *dev) |
1374 | { | 1547 | { |
1375 | return -EINVAL; | 1548 | return !!netif_carrier_ok(dev); |
1376 | } | 1549 | } |
1377 | 1550 | ||
1378 | static u32 mv643xx_eth_get_link(struct net_device *dev) | 1551 | static int |
1552 | mv643xx_eth_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) | ||
1379 | { | 1553 | { |
1380 | return !!netif_carrier_ok(dev); | 1554 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1555 | |||
1556 | ec->rx_coalesce_usecs = get_rx_coal(mp); | ||
1557 | ec->tx_coalesce_usecs = get_tx_coal(mp); | ||
1558 | |||
1559 | return 0; | ||
1560 | } | ||
1561 | |||
1562 | static int | ||
1563 | mv643xx_eth_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) | ||
1564 | { | ||
1565 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1566 | |||
1567 | set_rx_coal(mp, ec->rx_coalesce_usecs); | ||
1568 | set_tx_coal(mp, ec->tx_coalesce_usecs); | ||
1569 | |||
1570 | return 0; | ||
1571 | } | ||
1572 | |||
1573 | static void | ||
1574 | mv643xx_eth_get_ringparam(struct net_device *dev, struct ethtool_ringparam *er) | ||
1575 | { | ||
1576 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1577 | |||
1578 | er->rx_max_pending = 4096; | ||
1579 | er->tx_max_pending = 4096; | ||
1580 | er->rx_mini_max_pending = 0; | ||
1581 | er->rx_jumbo_max_pending = 0; | ||
1582 | |||
1583 | er->rx_pending = mp->rx_ring_size; | ||
1584 | er->tx_pending = mp->tx_ring_size; | ||
1585 | er->rx_mini_pending = 0; | ||
1586 | er->rx_jumbo_pending = 0; | ||
1587 | } | ||
1588 | |||
1589 | static int | ||
1590 | mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er) | ||
1591 | { | ||
1592 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1593 | |||
1594 | if (er->rx_mini_pending || er->rx_jumbo_pending) | ||
1595 | return -EINVAL; | ||
1596 | |||
1597 | mp->rx_ring_size = er->rx_pending < 4096 ? er->rx_pending : 4096; | ||
1598 | mp->tx_ring_size = er->tx_pending < 4096 ? er->tx_pending : 4096; | ||
1599 | |||
1600 | if (netif_running(dev)) { | ||
1601 | mv643xx_eth_stop(dev); | ||
1602 | if (mv643xx_eth_open(dev)) { | ||
1603 | dev_printk(KERN_ERR, &dev->dev, | ||
1604 | "fatal error on re-opening device after " | ||
1605 | "ring param change\n"); | ||
1606 | return -ENOMEM; | ||
1607 | } | ||
1608 | } | ||
1609 | |||
1610 | return 0; | ||
1611 | } | ||
1612 | |||
1613 | static u32 | ||
1614 | mv643xx_eth_get_rx_csum(struct net_device *dev) | ||
1615 | { | ||
1616 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1617 | |||
1618 | return !!(rdlp(mp, PORT_CONFIG) & 0x02000000); | ||
1619 | } | ||
1620 | |||
1621 | static int | ||
1622 | mv643xx_eth_set_rx_csum(struct net_device *dev, u32 rx_csum) | ||
1623 | { | ||
1624 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1625 | |||
1626 | wrlp(mp, PORT_CONFIG, rx_csum ? 0x02000000 : 0x00000000); | ||
1627 | |||
1628 | return 0; | ||
1381 | } | 1629 | } |
1382 | 1630 | ||
1383 | static void mv643xx_eth_get_strings(struct net_device *dev, | 1631 | static void mv643xx_eth_get_strings(struct net_device *dev, |
@@ -1403,6 +1651,7 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev, | |||
1403 | 1651 | ||
1404 | mv643xx_eth_get_stats(dev); | 1652 | mv643xx_eth_get_stats(dev); |
1405 | mib_counters_update(mp); | 1653 | mib_counters_update(mp); |
1654 | mv643xx_eth_grab_lro_stats(mp); | ||
1406 | 1655 | ||
1407 | for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) { | 1656 | for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) { |
1408 | const struct mv643xx_eth_stats *stat; | 1657 | const struct mv643xx_eth_stats *stat; |
@@ -1434,21 +1683,18 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = { | |||
1434 | .get_drvinfo = mv643xx_eth_get_drvinfo, | 1683 | .get_drvinfo = mv643xx_eth_get_drvinfo, |
1435 | .nway_reset = mv643xx_eth_nway_reset, | 1684 | .nway_reset = mv643xx_eth_nway_reset, |
1436 | .get_link = mv643xx_eth_get_link, | 1685 | .get_link = mv643xx_eth_get_link, |
1686 | .get_coalesce = mv643xx_eth_get_coalesce, | ||
1687 | .set_coalesce = mv643xx_eth_set_coalesce, | ||
1688 | .get_ringparam = mv643xx_eth_get_ringparam, | ||
1689 | .set_ringparam = mv643xx_eth_set_ringparam, | ||
1690 | .get_rx_csum = mv643xx_eth_get_rx_csum, | ||
1691 | .set_rx_csum = mv643xx_eth_set_rx_csum, | ||
1692 | .set_tx_csum = ethtool_op_set_tx_csum, | ||
1437 | .set_sg = ethtool_op_set_sg, | 1693 | .set_sg = ethtool_op_set_sg, |
1438 | .get_strings = mv643xx_eth_get_strings, | 1694 | .get_strings = mv643xx_eth_get_strings, |
1439 | .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, | 1695 | .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, |
1440 | .get_sset_count = mv643xx_eth_get_sset_count, | 1696 | .get_flags = ethtool_op_get_flags, |
1441 | }; | 1697 | .set_flags = ethtool_op_set_flags, |
1442 | |||
1443 | static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = { | ||
1444 | .get_settings = mv643xx_eth_get_settings_phyless, | ||
1445 | .set_settings = mv643xx_eth_set_settings_phyless, | ||
1446 | .get_drvinfo = mv643xx_eth_get_drvinfo, | ||
1447 | .nway_reset = mv643xx_eth_nway_reset_phyless, | ||
1448 | .get_link = mv643xx_eth_get_link, | ||
1449 | .set_sg = ethtool_op_set_sg, | ||
1450 | .get_strings = mv643xx_eth_get_strings, | ||
1451 | .get_ethtool_stats = mv643xx_eth_get_ethtool_stats, | ||
1452 | .get_sset_count = mv643xx_eth_get_sset_count, | 1698 | .get_sset_count = mv643xx_eth_get_sset_count, |
1453 | }; | 1699 | }; |
1454 | 1700 | ||
@@ -1637,7 +1883,7 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) | |||
1637 | 1883 | ||
1638 | rxq->index = index; | 1884 | rxq->index = index; |
1639 | 1885 | ||
1640 | rxq->rx_ring_size = mp->default_rx_ring_size; | 1886 | rxq->rx_ring_size = mp->rx_ring_size; |
1641 | 1887 | ||
1642 | rxq->rx_desc_count = 0; | 1888 | rxq->rx_desc_count = 0; |
1643 | rxq->rx_curr_desc = 0; | 1889 | rxq->rx_curr_desc = 0; |
@@ -1683,6 +1929,19 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index) | |||
1683 | nexti * sizeof(struct rx_desc); | 1929 | nexti * sizeof(struct rx_desc); |
1684 | } | 1930 | } |
1685 | 1931 | ||
1932 | rxq->lro_mgr.dev = mp->dev; | ||
1933 | memset(&rxq->lro_mgr.stats, 0, sizeof(rxq->lro_mgr.stats)); | ||
1934 | rxq->lro_mgr.features = LRO_F_NAPI; | ||
1935 | rxq->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; | ||
1936 | rxq->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; | ||
1937 | rxq->lro_mgr.max_desc = ARRAY_SIZE(rxq->lro_arr); | ||
1938 | rxq->lro_mgr.max_aggr = 32; | ||
1939 | rxq->lro_mgr.frag_align_pad = 0; | ||
1940 | rxq->lro_mgr.lro_arr = rxq->lro_arr; | ||
1941 | rxq->lro_mgr.get_skb_header = mv643xx_get_skb_header; | ||
1942 | |||
1943 | memset(&rxq->lro_arr, 0, sizeof(rxq->lro_arr)); | ||
1944 | |||
1686 | return 0; | 1945 | return 0; |
1687 | 1946 | ||
1688 | 1947 | ||
@@ -1737,7 +1996,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) | |||
1737 | 1996 | ||
1738 | txq->index = index; | 1997 | txq->index = index; |
1739 | 1998 | ||
1740 | txq->tx_ring_size = mp->default_tx_ring_size; | 1999 | txq->tx_ring_size = mp->tx_ring_size; |
1741 | 2000 | ||
1742 | txq->tx_desc_count = 0; | 2001 | txq->tx_desc_count = 0; |
1743 | txq->tx_curr_desc = 0; | 2002 | txq->tx_curr_desc = 0; |
@@ -2061,36 +2320,6 @@ static void port_start(struct mv643xx_eth_private *mp) | |||
2061 | } | 2320 | } |
2062 | } | 2321 | } |
2063 | 2322 | ||
2064 | static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int delay) | ||
2065 | { | ||
2066 | unsigned int coal = ((mp->shared->t_clk / 1000000) * delay) / 64; | ||
2067 | u32 val; | ||
2068 | |||
2069 | val = rdlp(mp, SDMA_CONFIG); | ||
2070 | if (mp->shared->extended_rx_coal_limit) { | ||
2071 | if (coal > 0xffff) | ||
2072 | coal = 0xffff; | ||
2073 | val &= ~0x023fff80; | ||
2074 | val |= (coal & 0x8000) << 10; | ||
2075 | val |= (coal & 0x7fff) << 7; | ||
2076 | } else { | ||
2077 | if (coal > 0x3fff) | ||
2078 | coal = 0x3fff; | ||
2079 | val &= ~0x003fff00; | ||
2080 | val |= (coal & 0x3fff) << 8; | ||
2081 | } | ||
2082 | wrlp(mp, SDMA_CONFIG, val); | ||
2083 | } | ||
2084 | |||
2085 | static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int delay) | ||
2086 | { | ||
2087 | unsigned int coal = ((mp->shared->t_clk / 1000000) * delay) / 64; | ||
2088 | |||
2089 | if (coal > 0x3fff) | ||
2090 | coal = 0x3fff; | ||
2091 | wrlp(mp, TX_FIFO_URGENT_THRESHOLD, (coal & 0x3fff) << 4); | ||
2092 | } | ||
2093 | |||
2094 | static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) | 2323 | static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp) |
2095 | { | 2324 | { |
2096 | int skb_size; | 2325 | int skb_size; |
@@ -2159,13 +2388,8 @@ static int mv643xx_eth_open(struct net_device *dev) | |||
2159 | } | 2388 | } |
2160 | } | 2389 | } |
2161 | 2390 | ||
2162 | netif_carrier_off(dev); | ||
2163 | |||
2164 | port_start(mp); | 2391 | port_start(mp); |
2165 | 2392 | ||
2166 | set_rx_coal(mp, 0); | ||
2167 | set_tx_coal(mp, 0); | ||
2168 | |||
2169 | wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); | 2393 | wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); |
2170 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); | 2394 | wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); |
2171 | 2395 | ||
@@ -2531,17 +2755,17 @@ static void set_params(struct mv643xx_eth_private *mp, | |||
2531 | else | 2755 | else |
2532 | uc_addr_get(mp, dev->dev_addr); | 2756 | uc_addr_get(mp, dev->dev_addr); |
2533 | 2757 | ||
2534 | mp->default_rx_ring_size = DEFAULT_RX_QUEUE_SIZE; | 2758 | mp->rx_ring_size = DEFAULT_RX_QUEUE_SIZE; |
2535 | if (pd->rx_queue_size) | 2759 | if (pd->rx_queue_size) |
2536 | mp->default_rx_ring_size = pd->rx_queue_size; | 2760 | mp->rx_ring_size = pd->rx_queue_size; |
2537 | mp->rx_desc_sram_addr = pd->rx_sram_addr; | 2761 | mp->rx_desc_sram_addr = pd->rx_sram_addr; |
2538 | mp->rx_desc_sram_size = pd->rx_sram_size; | 2762 | mp->rx_desc_sram_size = pd->rx_sram_size; |
2539 | 2763 | ||
2540 | mp->rxq_count = pd->rx_queue_count ? : 1; | 2764 | mp->rxq_count = pd->rx_queue_count ? : 1; |
2541 | 2765 | ||
2542 | mp->default_tx_ring_size = DEFAULT_TX_QUEUE_SIZE; | 2766 | mp->tx_ring_size = DEFAULT_TX_QUEUE_SIZE; |
2543 | if (pd->tx_queue_size) | 2767 | if (pd->tx_queue_size) |
2544 | mp->default_tx_ring_size = pd->tx_queue_size; | 2768 | mp->tx_ring_size = pd->tx_queue_size; |
2545 | mp->tx_desc_sram_addr = pd->tx_sram_addr; | 2769 | mp->tx_desc_sram_addr = pd->tx_sram_addr; |
2546 | mp->tx_desc_sram_size = pd->tx_sram_size; | 2770 | mp->tx_desc_sram_size = pd->tx_sram_size; |
2547 | 2771 | ||
@@ -2588,7 +2812,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) | |||
2588 | 2812 | ||
2589 | phy_reset(mp); | 2813 | phy_reset(mp); |
2590 | 2814 | ||
2591 | phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); | 2815 | phy_attach(mp->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_GMII); |
2592 | 2816 | ||
2593 | if (speed == 0) { | 2817 | if (speed == 0) { |
2594 | phy->autoneg = AUTONEG_ENABLE; | 2818 | phy->autoneg = AUTONEG_ENABLE; |
@@ -2632,6 +2856,21 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex) | |||
2632 | wrlp(mp, PORT_SERIAL_CONTROL, pscr); | 2856 | wrlp(mp, PORT_SERIAL_CONTROL, pscr); |
2633 | } | 2857 | } |
2634 | 2858 | ||
2859 | static const struct net_device_ops mv643xx_eth_netdev_ops = { | ||
2860 | .ndo_open = mv643xx_eth_open, | ||
2861 | .ndo_stop = mv643xx_eth_stop, | ||
2862 | .ndo_start_xmit = mv643xx_eth_xmit, | ||
2863 | .ndo_set_rx_mode = mv643xx_eth_set_rx_mode, | ||
2864 | .ndo_set_mac_address = mv643xx_eth_set_mac_address, | ||
2865 | .ndo_do_ioctl = mv643xx_eth_ioctl, | ||
2866 | .ndo_change_mtu = mv643xx_eth_change_mtu, | ||
2867 | .ndo_tx_timeout = mv643xx_eth_tx_timeout, | ||
2868 | .ndo_get_stats = mv643xx_eth_get_stats, | ||
2869 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
2870 | .ndo_poll_controller = mv643xx_eth_netpoll, | ||
2871 | #endif | ||
2872 | }; | ||
2873 | |||
2635 | static int mv643xx_eth_probe(struct platform_device *pdev) | 2874 | static int mv643xx_eth_probe(struct platform_device *pdev) |
2636 | { | 2875 | { |
2637 | struct mv643xx_eth_platform_data *pd; | 2876 | struct mv643xx_eth_platform_data *pd; |
@@ -2672,12 +2911,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2672 | if (pd->phy_addr != MV643XX_ETH_PHY_NONE) | 2911 | if (pd->phy_addr != MV643XX_ETH_PHY_NONE) |
2673 | mp->phy = phy_scan(mp, pd->phy_addr); | 2912 | mp->phy = phy_scan(mp, pd->phy_addr); |
2674 | 2913 | ||
2675 | if (mp->phy != NULL) { | 2914 | if (mp->phy != NULL) |
2676 | phy_init(mp, pd->speed, pd->duplex); | 2915 | phy_init(mp, pd->speed, pd->duplex); |
2677 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); | 2916 | |
2678 | } else { | 2917 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); |
2679 | SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless); | ||
2680 | } | ||
2681 | 2918 | ||
2682 | init_pscr(mp, pd->speed, pd->duplex); | 2919 | init_pscr(mp, pd->speed, pd->duplex); |
2683 | 2920 | ||
@@ -2705,18 +2942,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2705 | BUG_ON(!res); | 2942 | BUG_ON(!res); |
2706 | dev->irq = res->start; | 2943 | dev->irq = res->start; |
2707 | 2944 | ||
2708 | dev->get_stats = mv643xx_eth_get_stats; | 2945 | dev->netdev_ops = &mv643xx_eth_netdev_ops; |
2709 | dev->hard_start_xmit = mv643xx_eth_xmit; | 2946 | |
2710 | dev->open = mv643xx_eth_open; | ||
2711 | dev->stop = mv643xx_eth_stop; | ||
2712 | dev->set_rx_mode = mv643xx_eth_set_rx_mode; | ||
2713 | dev->set_mac_address = mv643xx_eth_set_mac_address; | ||
2714 | dev->do_ioctl = mv643xx_eth_ioctl; | ||
2715 | dev->change_mtu = mv643xx_eth_change_mtu; | ||
2716 | dev->tx_timeout = mv643xx_eth_tx_timeout; | ||
2717 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
2718 | dev->poll_controller = mv643xx_eth_netpoll; | ||
2719 | #endif | ||
2720 | dev->watchdog_timeo = 2 * HZ; | 2947 | dev->watchdog_timeo = 2 * HZ; |
2721 | dev->base_addr = 0; | 2948 | dev->base_addr = 0; |
2722 | 2949 | ||
@@ -2728,6 +2955,11 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2728 | if (mp->shared->win_protect) | 2955 | if (mp->shared->win_protect) |
2729 | wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect); | 2956 | wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect); |
2730 | 2957 | ||
2958 | netif_carrier_off(dev); | ||
2959 | |||
2960 | set_rx_coal(mp, 250); | ||
2961 | set_tx_coal(mp, 0); | ||
2962 | |||
2731 | err = register_netdev(dev); | 2963 | err = register_netdev(dev); |
2732 | if (err) | 2964 | if (err) |
2733 | goto out; | 2965 | goto out; |