diff options
author | Greg KH <greg@press.(none)> | 2005-10-28 13:13:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 13:13:16 -0400 |
commit | 6fbfddcb52d8d9fa2cd209f5ac2a1c87497d55b5 (patch) | |
tree | c0414e89678fcef7ce3493e048d855bde781ae8d /drivers/net/via-rhine.c | |
parent | 1a222bca26ca691e83be1b08f5e96ae96d0d8cae (diff) | |
parent | 27d1097d39509494706eaa2620ef3b1e780a3224 (diff) |
Merge ../bleed-2.6
Diffstat (limited to 'drivers/net/via-rhine.c')
-rw-r--r-- | drivers/net/via-rhine.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index fc7738ffbfff..241871589283 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c | |||
@@ -490,6 +490,8 @@ struct rhine_private { | |||
490 | u8 tx_thresh, rx_thresh; | 490 | u8 tx_thresh, rx_thresh; |
491 | 491 | ||
492 | struct mii_if_info mii_if; | 492 | struct mii_if_info mii_if; |
493 | struct work_struct tx_timeout_task; | ||
494 | struct work_struct check_media_task; | ||
493 | void __iomem *base; | 495 | void __iomem *base; |
494 | }; | 496 | }; |
495 | 497 | ||
@@ -497,6 +499,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location); | |||
497 | static void mdio_write(struct net_device *dev, int phy_id, int location, int value); | 499 | static void mdio_write(struct net_device *dev, int phy_id, int location, int value); |
498 | static int rhine_open(struct net_device *dev); | 500 | static int rhine_open(struct net_device *dev); |
499 | static void rhine_tx_timeout(struct net_device *dev); | 501 | static void rhine_tx_timeout(struct net_device *dev); |
502 | static void rhine_tx_timeout_task(struct net_device *dev); | ||
503 | static void rhine_check_media_task(struct net_device *dev); | ||
500 | static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); | 504 | static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); |
501 | static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); | 505 | static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); |
502 | static void rhine_tx(struct net_device *dev); | 506 | static void rhine_tx(struct net_device *dev); |
@@ -814,8 +818,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, | |||
814 | 818 | ||
815 | for (i = 0; i < 6; i++) | 819 | for (i = 0; i < 6; i++) |
816 | dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i); | 820 | dev->dev_addr[i] = ioread8(ioaddr + StationAddr + i); |
821 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); | ||
817 | 822 | ||
818 | if (!is_valid_ether_addr(dev->dev_addr)) { | 823 | if (!is_valid_ether_addr(dev->perm_addr)) { |
819 | rc = -EIO; | 824 | rc = -EIO; |
820 | printk(KERN_ERR "Invalid MAC address\n"); | 825 | printk(KERN_ERR "Invalid MAC address\n"); |
821 | goto err_out_unmap; | 826 | goto err_out_unmap; |
@@ -850,6 +855,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, | |||
850 | if (rp->quirks & rqRhineI) | 855 | if (rp->quirks & rqRhineI) |
851 | dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; | 856 | dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; |
852 | 857 | ||
858 | INIT_WORK(&rp->tx_timeout_task, | ||
859 | (void (*)(void *))rhine_tx_timeout_task, dev); | ||
860 | |||
861 | INIT_WORK(&rp->check_media_task, | ||
862 | (void (*)(void *))rhine_check_media_task, dev); | ||
863 | |||
853 | /* dev->name not defined before register_netdev()! */ | 864 | /* dev->name not defined before register_netdev()! */ |
854 | rc = register_netdev(dev); | 865 | rc = register_netdev(dev); |
855 | if (rc) | 866 | if (rc) |
@@ -1076,6 +1087,11 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) | |||
1076 | ioaddr + ChipCmd1); | 1087 | ioaddr + ChipCmd1); |
1077 | } | 1088 | } |
1078 | 1089 | ||
1090 | static void rhine_check_media_task(struct net_device *dev) | ||
1091 | { | ||
1092 | rhine_check_media(dev, 0); | ||
1093 | } | ||
1094 | |||
1079 | static void init_registers(struct net_device *dev) | 1095 | static void init_registers(struct net_device *dev) |
1080 | { | 1096 | { |
1081 | struct rhine_private *rp = netdev_priv(dev); | 1097 | struct rhine_private *rp = netdev_priv(dev); |
@@ -1129,8 +1145,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks) | |||
1129 | if (quirks & rqRhineI) { | 1145 | if (quirks & rqRhineI) { |
1130 | iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR | 1146 | iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR |
1131 | 1147 | ||
1132 | /* Can be called from ISR. Evil. */ | 1148 | /* Do not call from ISR! */ |
1133 | mdelay(1); | 1149 | msleep(1); |
1134 | 1150 | ||
1135 | /* 0x80 must be set immediately before turning it off */ | 1151 | /* 0x80 must be set immediately before turning it off */ |
1136 | iowrite8(0x80, ioaddr + MIICmd); | 1152 | iowrite8(0x80, ioaddr + MIICmd); |
@@ -1220,6 +1236,16 @@ static int rhine_open(struct net_device *dev) | |||
1220 | static void rhine_tx_timeout(struct net_device *dev) | 1236 | static void rhine_tx_timeout(struct net_device *dev) |
1221 | { | 1237 | { |
1222 | struct rhine_private *rp = netdev_priv(dev); | 1238 | struct rhine_private *rp = netdev_priv(dev); |
1239 | |||
1240 | /* | ||
1241 | * Move bulk of work outside of interrupt context | ||
1242 | */ | ||
1243 | schedule_work(&rp->tx_timeout_task); | ||
1244 | } | ||
1245 | |||
1246 | static void rhine_tx_timeout_task(struct net_device *dev) | ||
1247 | { | ||
1248 | struct rhine_private *rp = netdev_priv(dev); | ||
1223 | void __iomem *ioaddr = rp->base; | 1249 | void __iomem *ioaddr = rp->base; |
1224 | 1250 | ||
1225 | printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " | 1251 | printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " |
@@ -1625,7 +1651,7 @@ static void rhine_error(struct net_device *dev, int intr_status) | |||
1625 | spin_lock(&rp->lock); | 1651 | spin_lock(&rp->lock); |
1626 | 1652 | ||
1627 | if (intr_status & IntrLinkChange) | 1653 | if (intr_status & IntrLinkChange) |
1628 | rhine_check_media(dev, 0); | 1654 | schedule_work(&rp->check_media_task); |
1629 | if (intr_status & IntrStatsMax) { | 1655 | if (intr_status & IntrStatsMax) { |
1630 | rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); | 1656 | rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); |
1631 | rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); | 1657 | rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); |
@@ -1829,6 +1855,7 @@ static struct ethtool_ops netdev_ethtool_ops = { | |||
1829 | .set_wol = rhine_set_wol, | 1855 | .set_wol = rhine_set_wol, |
1830 | .get_sg = ethtool_op_get_sg, | 1856 | .get_sg = ethtool_op_get_sg, |
1831 | .get_tx_csum = ethtool_op_get_tx_csum, | 1857 | .get_tx_csum = ethtool_op_get_tx_csum, |
1858 | .get_perm_addr = ethtool_op_get_perm_addr, | ||
1832 | }; | 1859 | }; |
1833 | 1860 | ||
1834 | static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 1861 | static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
@@ -1872,6 +1899,9 @@ static int rhine_close(struct net_device *dev) | |||
1872 | spin_unlock_irq(&rp->lock); | 1899 | spin_unlock_irq(&rp->lock); |
1873 | 1900 | ||
1874 | free_irq(rp->pdev->irq, dev); | 1901 | free_irq(rp->pdev->irq, dev); |
1902 | |||
1903 | flush_scheduled_work(); | ||
1904 | |||
1875 | free_rbufs(dev); | 1905 | free_rbufs(dev); |
1876 | free_tbufs(dev); | 1906 | free_tbufs(dev); |
1877 | free_ring(dev); | 1907 | free_ring(dev); |