aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dm9000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dm9000.c')
-rw-r--r--drivers/net/dm9000.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 7f9960f718e3..abcc838e18af 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -476,17 +476,13 @@ static uint32_t dm9000_get_rx_csum(struct net_device *dev)
476 return dm->rx_csum; 476 return dm->rx_csum;
477} 477}
478 478
479static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data) 479static int dm9000_set_rx_csum_unlocked(struct net_device *dev, uint32_t data)
480{ 480{
481 board_info_t *dm = to_dm9000_board(dev); 481 board_info_t *dm = to_dm9000_board(dev);
482 unsigned long flags;
483 482
484 if (dm->can_csum) { 483 if (dm->can_csum) {
485 dm->rx_csum = data; 484 dm->rx_csum = data;
486
487 spin_lock_irqsave(&dm->lock, flags);
488 iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0); 485 iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0);
489 spin_unlock_irqrestore(&dm->lock, flags);
490 486
491 return 0; 487 return 0;
492 } 488 }
@@ -494,6 +490,19 @@ static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
494 return -EOPNOTSUPP; 490 return -EOPNOTSUPP;
495} 491}
496 492
493static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
494{
495 board_info_t *dm = to_dm9000_board(dev);
496 unsigned long flags;
497 int ret;
498
499 spin_lock_irqsave(&dm->lock, flags);
500 ret = dm9000_set_rx_csum_unlocked(dev, data);
501 spin_unlock_irqrestore(&dm->lock, flags);
502
503 return ret;
504}
505
497static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data) 506static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data)
498{ 507{
499 board_info_t *dm = to_dm9000_board(dev); 508 board_info_t *dm = to_dm9000_board(dev);
@@ -722,20 +731,17 @@ static unsigned char dm9000_type_to_char(enum dm9000_type type)
722 * Set DM9000 multicast address 731 * Set DM9000 multicast address
723 */ 732 */
724static void 733static void
725dm9000_hash_table(struct net_device *dev) 734dm9000_hash_table_unlocked(struct net_device *dev)
726{ 735{
727 board_info_t *db = netdev_priv(dev); 736 board_info_t *db = netdev_priv(dev);
728 struct dev_mc_list *mcptr; 737 struct netdev_hw_addr *ha;
729 int i, oft; 738 int i, oft;
730 u32 hash_val; 739 u32 hash_val;
731 u16 hash_table[4]; 740 u16 hash_table[4];
732 u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN; 741 u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
733 unsigned long flags;
734 742
735 dm9000_dbg(db, 1, "entering %s\n", __func__); 743 dm9000_dbg(db, 1, "entering %s\n", __func__);
736 744
737 spin_lock_irqsave(&db->lock, flags);
738
739 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) 745 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
740 iow(db, oft, dev->dev_addr[i]); 746 iow(db, oft, dev->dev_addr[i]);
741 747
@@ -753,8 +759,8 @@ dm9000_hash_table(struct net_device *dev)
753 rcr |= RCR_ALL; 759 rcr |= RCR_ALL;
754 760
755 /* the multicast address in Hash Table : 64 bits */ 761 /* the multicast address in Hash Table : 64 bits */
756 netdev_for_each_mc_addr(mcptr, dev) { 762 netdev_for_each_mc_addr(ha, dev) {
757 hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; 763 hash_val = ether_crc_le(6, ha->addr) & 0x3f;
758 hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); 764 hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
759 } 765 }
760 766
@@ -765,11 +771,21 @@ dm9000_hash_table(struct net_device *dev)
765 } 771 }
766 772
767 iow(db, DM9000_RCR, rcr); 773 iow(db, DM9000_RCR, rcr);
774}
775
776static void
777dm9000_hash_table(struct net_device *dev)
778{
779 board_info_t *db = netdev_priv(dev);
780 unsigned long flags;
781
782 spin_lock_irqsave(&db->lock, flags);
783 dm9000_hash_table_unlocked(dev);
768 spin_unlock_irqrestore(&db->lock, flags); 784 spin_unlock_irqrestore(&db->lock, flags);
769} 785}
770 786
771/* 787/*
772 * Initilize dm9000 board 788 * Initialize dm9000 board
773 */ 789 */
774static void 790static void
775dm9000_init_dm9000(struct net_device *dev) 791dm9000_init_dm9000(struct net_device *dev)
@@ -784,7 +800,7 @@ dm9000_init_dm9000(struct net_device *dev)
784 db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ 800 db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
785 801
786 /* Checksum mode */ 802 /* Checksum mode */
787 dm9000_set_rx_csum(dev, db->rx_csum); 803 dm9000_set_rx_csum_unlocked(dev, db->rx_csum);
788 804
789 /* GPIO0 on pre-activate PHY */ 805 /* GPIO0 on pre-activate PHY */
790 iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ 806 iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
@@ -811,7 +827,7 @@ dm9000_init_dm9000(struct net_device *dev)
811 iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ 827 iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
812 828
813 /* Set address filter table */ 829 /* Set address filter table */
814 dm9000_hash_table(dev); 830 dm9000_hash_table_unlocked(dev);
815 831
816 imr = IMR_PAR | IMR_PTM | IMR_PRM; 832 imr = IMR_PAR | IMR_PTM | IMR_PRM;
817 if (db->type != TYPE_DM9000E) 833 if (db->type != TYPE_DM9000E)
@@ -825,7 +841,7 @@ dm9000_init_dm9000(struct net_device *dev)
825 /* Init Driver variable */ 841 /* Init Driver variable */
826 db->tx_pkt_cnt = 0; 842 db->tx_pkt_cnt = 0;
827 db->queue_pkt_len = 0; 843 db->queue_pkt_len = 0;
828 dev->trans_start = 0; 844 dev->trans_start = jiffies;
829} 845}
830 846
831/* Our watchdog timed out. Called by the networking layer */ 847/* Our watchdog timed out. Called by the networking layer */
@@ -843,7 +859,7 @@ static void dm9000_timeout(struct net_device *dev)
843 dm9000_reset(db); 859 dm9000_reset(db);
844 dm9000_init_dm9000(dev); 860 dm9000_init_dm9000(dev);
845 /* We can accept TX packets again */ 861 /* We can accept TX packets again */
846 dev->trans_start = jiffies; 862 dev->trans_start = jiffies; /* prevent tx timeout */
847 netif_wake_queue(dev); 863 netif_wake_queue(dev);
848 864
849 /* Restore previous register address */ 865 /* Restore previous register address */