diff options
Diffstat (limited to 'drivers/net/dm9000.c')
-rw-r--r-- | drivers/net/dm9000.c | 127 |
1 files changed, 103 insertions, 24 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index dd771dea6ae6..a2bc4158259a 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c | |||
@@ -92,6 +92,7 @@ typedef struct board_info { | |||
92 | u16 tx_pkt_cnt; | 92 | u16 tx_pkt_cnt; |
93 | u16 queue_pkt_len; | 93 | u16 queue_pkt_len; |
94 | u16 queue_start_addr; | 94 | u16 queue_start_addr; |
95 | u16 queue_ip_summed; | ||
95 | u16 dbug_cnt; | 96 | u16 dbug_cnt; |
96 | u8 io_mode; /* 0:word, 2:byte */ | 97 | u8 io_mode; /* 0:word, 2:byte */ |
97 | u8 phy_addr; | 98 | u8 phy_addr; |
@@ -124,6 +125,10 @@ typedef struct board_info { | |||
124 | 125 | ||
125 | struct mii_if_info mii; | 126 | struct mii_if_info mii; |
126 | u32 msg_enable; | 127 | u32 msg_enable; |
128 | |||
129 | int rx_csum; | ||
130 | int can_csum; | ||
131 | int ip_summed; | ||
127 | } board_info_t; | 132 | } board_info_t; |
128 | 133 | ||
129 | /* debug code */ | 134 | /* debug code */ |
@@ -460,6 +465,40 @@ static int dm9000_nway_reset(struct net_device *dev) | |||
460 | return mii_nway_restart(&dm->mii); | 465 | return mii_nway_restart(&dm->mii); |
461 | } | 466 | } |
462 | 467 | ||
468 | static uint32_t dm9000_get_rx_csum(struct net_device *dev) | ||
469 | { | ||
470 | board_info_t *dm = to_dm9000_board(dev); | ||
471 | return dm->rx_csum; | ||
472 | } | ||
473 | |||
474 | static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data) | ||
475 | { | ||
476 | board_info_t *dm = to_dm9000_board(dev); | ||
477 | unsigned long flags; | ||
478 | |||
479 | if (dm->can_csum) { | ||
480 | dm->rx_csum = data; | ||
481 | |||
482 | spin_lock_irqsave(&dm->lock, flags); | ||
483 | iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0); | ||
484 | spin_unlock_irqrestore(&dm->lock, flags); | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | return -EOPNOTSUPP; | ||
490 | } | ||
491 | |||
492 | static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data) | ||
493 | { | ||
494 | board_info_t *dm = to_dm9000_board(dev); | ||
495 | int ret = -EOPNOTSUPP; | ||
496 | |||
497 | if (dm->can_csum) | ||
498 | ret = ethtool_op_set_tx_csum(dev, data); | ||
499 | return ret; | ||
500 | } | ||
501 | |||
463 | static u32 dm9000_get_link(struct net_device *dev) | 502 | static u32 dm9000_get_link(struct net_device *dev) |
464 | { | 503 | { |
465 | board_info_t *dm = to_dm9000_board(dev); | 504 | board_info_t *dm = to_dm9000_board(dev); |
@@ -540,6 +579,10 @@ static const struct ethtool_ops dm9000_ethtool_ops = { | |||
540 | .get_eeprom_len = dm9000_get_eeprom_len, | 579 | .get_eeprom_len = dm9000_get_eeprom_len, |
541 | .get_eeprom = dm9000_get_eeprom, | 580 | .get_eeprom = dm9000_get_eeprom, |
542 | .set_eeprom = dm9000_set_eeprom, | 581 | .set_eeprom = dm9000_set_eeprom, |
582 | .get_rx_csum = dm9000_get_rx_csum, | ||
583 | .set_rx_csum = dm9000_set_rx_csum, | ||
584 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
585 | .set_tx_csum = dm9000_set_tx_csum, | ||
543 | }; | 586 | }; |
544 | 587 | ||
545 | static void dm9000_show_carrier(board_info_t *db, | 588 | static void dm9000_show_carrier(board_info_t *db, |
@@ -685,6 +728,9 @@ dm9000_init_dm9000(struct net_device *dev) | |||
685 | /* I/O mode */ | 728 | /* I/O mode */ |
686 | db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ | 729 | db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ |
687 | 730 | ||
731 | /* Checksum mode */ | ||
732 | dm9000_set_rx_csum(dev, db->rx_csum); | ||
733 | |||
688 | /* GPIO0 on pre-activate PHY */ | 734 | /* GPIO0 on pre-activate PHY */ |
689 | iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ | 735 | iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ |
690 | iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ | 736 | iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ |
@@ -743,6 +789,29 @@ static void dm9000_timeout(struct net_device *dev) | |||
743 | spin_unlock_irqrestore(&db->lock, flags); | 789 | spin_unlock_irqrestore(&db->lock, flags); |
744 | } | 790 | } |
745 | 791 | ||
792 | static void dm9000_send_packet(struct net_device *dev, | ||
793 | int ip_summed, | ||
794 | u16 pkt_len) | ||
795 | { | ||
796 | board_info_t *dm = to_dm9000_board(dev); | ||
797 | |||
798 | /* The DM9000 is not smart enough to leave fragmented packets alone. */ | ||
799 | if (dm->ip_summed != ip_summed) { | ||
800 | if (ip_summed == CHECKSUM_NONE) | ||
801 | iow(dm, DM9000_TCCR, 0); | ||
802 | else | ||
803 | iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP); | ||
804 | dm->ip_summed = ip_summed; | ||
805 | } | ||
806 | |||
807 | /* Set TX length to DM9000 */ | ||
808 | iow(dm, DM9000_TXPLL, pkt_len); | ||
809 | iow(dm, DM9000_TXPLH, pkt_len >> 8); | ||
810 | |||
811 | /* Issue TX polling command */ | ||
812 | iow(dm, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ | ||
813 | } | ||
814 | |||
746 | /* | 815 | /* |
747 | * Hardware start transmission. | 816 | * Hardware start transmission. |
748 | * Send a packet to media from the upper layer. | 817 | * Send a packet to media from the upper layer. |
@@ -769,17 +838,11 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
769 | db->tx_pkt_cnt++; | 838 | db->tx_pkt_cnt++; |
770 | /* TX control: First packet immediately send, second packet queue */ | 839 | /* TX control: First packet immediately send, second packet queue */ |
771 | if (db->tx_pkt_cnt == 1) { | 840 | if (db->tx_pkt_cnt == 1) { |
772 | /* Set TX length to DM9000 */ | 841 | dm9000_send_packet(dev, skb->ip_summed, skb->len); |
773 | iow(db, DM9000_TXPLL, skb->len); | ||
774 | iow(db, DM9000_TXPLH, skb->len >> 8); | ||
775 | |||
776 | /* Issue TX polling command */ | ||
777 | iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ | ||
778 | |||
779 | dev->trans_start = jiffies; /* save the time stamp */ | ||
780 | } else { | 842 | } else { |
781 | /* Second packet */ | 843 | /* Second packet */ |
782 | db->queue_pkt_len = skb->len; | 844 | db->queue_pkt_len = skb->len; |
845 | db->queue_ip_summed = skb->ip_summed; | ||
783 | netif_stop_queue(dev); | 846 | netif_stop_queue(dev); |
784 | } | 847 | } |
785 | 848 | ||
@@ -788,7 +851,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
788 | /* free this SKB */ | 851 | /* free this SKB */ |
789 | dev_kfree_skb(skb); | 852 | dev_kfree_skb(skb); |
790 | 853 | ||
791 | return 0; | 854 | return NETDEV_TX_OK; |
792 | } | 855 | } |
793 | 856 | ||
794 | /* | 857 | /* |
@@ -809,12 +872,9 @@ static void dm9000_tx_done(struct net_device *dev, board_info_t *db) | |||
809 | dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status); | 872 | dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status); |
810 | 873 | ||
811 | /* Queue packet check & send */ | 874 | /* Queue packet check & send */ |
812 | if (db->tx_pkt_cnt > 0) { | 875 | if (db->tx_pkt_cnt > 0) |
813 | iow(db, DM9000_TXPLL, db->queue_pkt_len); | 876 | dm9000_send_packet(dev, db->queue_ip_summed, |
814 | iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8); | 877 | db->queue_pkt_len); |
815 | iow(db, DM9000_TCR, TCR_TXREQ); | ||
816 | dev->trans_start = jiffies; | ||
817 | } | ||
818 | netif_wake_queue(dev); | 878 | netif_wake_queue(dev); |
819 | } | 879 | } |
820 | } | 880 | } |
@@ -846,14 +906,14 @@ dm9000_rx(struct net_device *dev) | |||
846 | rxbyte = readb(db->io_data); | 906 | rxbyte = readb(db->io_data); |
847 | 907 | ||
848 | /* Status check: this byte must be 0 or 1 */ | 908 | /* Status check: this byte must be 0 or 1 */ |
849 | if (rxbyte > DM9000_PKT_RDY) { | 909 | if (rxbyte & DM9000_PKT_ERR) { |
850 | dev_warn(db->dev, "status check fail: %d\n", rxbyte); | 910 | dev_warn(db->dev, "status check fail: %d\n", rxbyte); |
851 | iow(db, DM9000_RCR, 0x00); /* Stop Device */ | 911 | iow(db, DM9000_RCR, 0x00); /* Stop Device */ |
852 | iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ | 912 | iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ |
853 | return; | 913 | return; |
854 | } | 914 | } |
855 | 915 | ||
856 | if (rxbyte != DM9000_PKT_RDY) | 916 | if (!(rxbyte & DM9000_PKT_RDY)) |
857 | return; | 917 | return; |
858 | 918 | ||
859 | /* A packet ready now & Get status/length */ | 919 | /* A packet ready now & Get status/length */ |
@@ -914,6 +974,12 @@ dm9000_rx(struct net_device *dev) | |||
914 | 974 | ||
915 | /* Pass to upper layer */ | 975 | /* Pass to upper layer */ |
916 | skb->protocol = eth_type_trans(skb, dev); | 976 | skb->protocol = eth_type_trans(skb, dev); |
977 | if (db->rx_csum) { | ||
978 | if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0) | ||
979 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
980 | else | ||
981 | skb->ip_summed = CHECKSUM_NONE; | ||
982 | } | ||
917 | netif_rx(skb); | 983 | netif_rx(skb); |
918 | dev->stats.rx_packets++; | 984 | dev->stats.rx_packets++; |
919 | 985 | ||
@@ -922,7 +988,7 @@ dm9000_rx(struct net_device *dev) | |||
922 | 988 | ||
923 | (db->dumpblk)(db->io_data, RxLen); | 989 | (db->dumpblk)(db->io_data, RxLen); |
924 | } | 990 | } |
925 | } while (rxbyte == DM9000_PKT_RDY); | 991 | } while (rxbyte & DM9000_PKT_RDY); |
926 | } | 992 | } |
927 | 993 | ||
928 | static irqreturn_t dm9000_interrupt(int irq, void *dev_id) | 994 | static irqreturn_t dm9000_interrupt(int irq, void *dev_id) |
@@ -1349,6 +1415,13 @@ dm9000_probe(struct platform_device *pdev) | |||
1349 | db->type = TYPE_DM9000E; | 1415 | db->type = TYPE_DM9000E; |
1350 | } | 1416 | } |
1351 | 1417 | ||
1418 | /* dm9000a/b are capable of hardware checksum offload */ | ||
1419 | if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) { | ||
1420 | db->can_csum = 1; | ||
1421 | db->rx_csum = 1; | ||
1422 | ndev->features |= NETIF_F_IP_CSUM; | ||
1423 | } | ||
1424 | |||
1352 | /* from this point we assume that we have found a DM9000 */ | 1425 | /* from this point we assume that we have found a DM9000 */ |
1353 | 1426 | ||
1354 | /* driver system function */ | 1427 | /* driver system function */ |
@@ -1410,9 +1483,10 @@ out: | |||
1410 | } | 1483 | } |
1411 | 1484 | ||
1412 | static int | 1485 | static int |
1413 | dm9000_drv_suspend(struct platform_device *dev, pm_message_t state) | 1486 | dm9000_drv_suspend(struct device *dev) |
1414 | { | 1487 | { |
1415 | struct net_device *ndev = platform_get_drvdata(dev); | 1488 | struct platform_device *pdev = to_platform_device(dev); |
1489 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
1416 | board_info_t *db; | 1490 | board_info_t *db; |
1417 | 1491 | ||
1418 | if (ndev) { | 1492 | if (ndev) { |
@@ -1428,9 +1502,10 @@ dm9000_drv_suspend(struct platform_device *dev, pm_message_t state) | |||
1428 | } | 1502 | } |
1429 | 1503 | ||
1430 | static int | 1504 | static int |
1431 | dm9000_drv_resume(struct platform_device *dev) | 1505 | dm9000_drv_resume(struct device *dev) |
1432 | { | 1506 | { |
1433 | struct net_device *ndev = platform_get_drvdata(dev); | 1507 | struct platform_device *pdev = to_platform_device(dev); |
1508 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
1434 | board_info_t *db = netdev_priv(ndev); | 1509 | board_info_t *db = netdev_priv(ndev); |
1435 | 1510 | ||
1436 | if (ndev) { | 1511 | if (ndev) { |
@@ -1447,6 +1522,11 @@ dm9000_drv_resume(struct platform_device *dev) | |||
1447 | return 0; | 1522 | return 0; |
1448 | } | 1523 | } |
1449 | 1524 | ||
1525 | static struct dev_pm_ops dm9000_drv_pm_ops = { | ||
1526 | .suspend = dm9000_drv_suspend, | ||
1527 | .resume = dm9000_drv_resume, | ||
1528 | }; | ||
1529 | |||
1450 | static int __devexit | 1530 | static int __devexit |
1451 | dm9000_drv_remove(struct platform_device *pdev) | 1531 | dm9000_drv_remove(struct platform_device *pdev) |
1452 | { | 1532 | { |
@@ -1466,11 +1546,10 @@ static struct platform_driver dm9000_driver = { | |||
1466 | .driver = { | 1546 | .driver = { |
1467 | .name = "dm9000", | 1547 | .name = "dm9000", |
1468 | .owner = THIS_MODULE, | 1548 | .owner = THIS_MODULE, |
1549 | .pm = &dm9000_drv_pm_ops, | ||
1469 | }, | 1550 | }, |
1470 | .probe = dm9000_probe, | 1551 | .probe = dm9000_probe, |
1471 | .remove = __devexit_p(dm9000_drv_remove), | 1552 | .remove = __devexit_p(dm9000_drv_remove), |
1472 | .suspend = dm9000_drv_suspend, | ||
1473 | .resume = dm9000_drv_resume, | ||
1474 | }; | 1553 | }; |
1475 | 1554 | ||
1476 | static int __init | 1555 | static int __init |