diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 276 |
1 files changed, 107 insertions, 169 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3a6c796eb70e..41dbe588de30 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -500,9 +500,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
500 | /* Force a renegotiation */ | 500 | /* Force a renegotiation */ |
501 | static void sky2_phy_reinit(struct sky2_port *sky2) | 501 | static void sky2_phy_reinit(struct sky2_port *sky2) |
502 | { | 502 | { |
503 | down(&sky2->phy_sema); | 503 | spin_lock_bh(&sky2->phy_lock); |
504 | sky2_phy_init(sky2->hw, sky2->port); | 504 | sky2_phy_init(sky2->hw, sky2->port); |
505 | up(&sky2->phy_sema); | 505 | spin_unlock_bh(&sky2->phy_lock); |
506 | } | 506 | } |
507 | 507 | ||
508 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | 508 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) |
@@ -567,9 +567,9 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
567 | 567 | ||
568 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); | 568 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); |
569 | 569 | ||
570 | down(&sky2->phy_sema); | 570 | spin_lock_bh(&sky2->phy_lock); |
571 | sky2_phy_init(hw, port); | 571 | sky2_phy_init(hw, port); |
572 | up(&sky2->phy_sema); | 572 | spin_unlock_bh(&sky2->phy_lock); |
573 | 573 | ||
574 | /* MIB clear */ | 574 | /* MIB clear */ |
575 | reg = gma_read16(hw, port, GM_PHY_ADDR); | 575 | reg = gma_read16(hw, port, GM_PHY_ADDR); |
@@ -856,9 +856,9 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
856 | case SIOCGMIIREG: { | 856 | case SIOCGMIIREG: { |
857 | u16 val = 0; | 857 | u16 val = 0; |
858 | 858 | ||
859 | down(&sky2->phy_sema); | 859 | spin_lock_bh(&sky2->phy_lock); |
860 | err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val); | 860 | err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val); |
861 | up(&sky2->phy_sema); | 861 | spin_unlock_bh(&sky2->phy_lock); |
862 | 862 | ||
863 | data->val_out = val; | 863 | data->val_out = val; |
864 | break; | 864 | break; |
@@ -868,10 +868,10 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
868 | if (!capable(CAP_NET_ADMIN)) | 868 | if (!capable(CAP_NET_ADMIN)) |
869 | return -EPERM; | 869 | return -EPERM; |
870 | 870 | ||
871 | down(&sky2->phy_sema); | 871 | spin_lock_bh(&sky2->phy_lock); |
872 | err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f, | 872 | err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f, |
873 | data->val_in); | 873 | data->val_in); |
874 | up(&sky2->phy_sema); | 874 | spin_unlock_bh(&sky2->phy_lock); |
875 | break; | 875 | break; |
876 | } | 876 | } |
877 | return err; | 877 | return err; |
@@ -983,7 +983,7 @@ static int sky2_up(struct net_device *dev) | |||
983 | struct sky2_port *sky2 = netdev_priv(dev); | 983 | struct sky2_port *sky2 = netdev_priv(dev); |
984 | struct sky2_hw *hw = sky2->hw; | 984 | struct sky2_hw *hw = sky2->hw; |
985 | unsigned port = sky2->port; | 985 | unsigned port = sky2->port; |
986 | u32 ramsize, rxspace; | 986 | u32 ramsize, rxspace, imask; |
987 | int err = -ENOMEM; | 987 | int err = -ENOMEM; |
988 | 988 | ||
989 | if (netif_msg_ifup(sky2)) | 989 | if (netif_msg_ifup(sky2)) |
@@ -1048,10 +1048,10 @@ static int sky2_up(struct net_device *dev) | |||
1048 | goto err_out; | 1048 | goto err_out; |
1049 | 1049 | ||
1050 | /* Enable interrupts from phy/mac for port */ | 1050 | /* Enable interrupts from phy/mac for port */ |
1051 | spin_lock_irq(&hw->hw_lock); | 1051 | imask = sky2_read32(hw, B0_IMSK); |
1052 | hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1052 | imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; |
1053 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1053 | sky2_write32(hw, B0_IMSK, imask); |
1054 | spin_unlock_irq(&hw->hw_lock); | 1054 | |
1055 | return 0; | 1055 | return 0; |
1056 | 1056 | ||
1057 | err_out: | 1057 | err_out: |
@@ -1343,6 +1343,7 @@ static int sky2_down(struct net_device *dev) | |||
1343 | struct sky2_hw *hw = sky2->hw; | 1343 | struct sky2_hw *hw = sky2->hw; |
1344 | unsigned port = sky2->port; | 1344 | unsigned port = sky2->port; |
1345 | u16 ctrl; | 1345 | u16 ctrl; |
1346 | u32 imask; | ||
1346 | 1347 | ||
1347 | /* Never really got started! */ | 1348 | /* Never really got started! */ |
1348 | if (!sky2->tx_le) | 1349 | if (!sky2->tx_le) |
@@ -1354,14 +1355,6 @@ static int sky2_down(struct net_device *dev) | |||
1354 | /* Stop more packets from being queued */ | 1355 | /* Stop more packets from being queued */ |
1355 | netif_stop_queue(dev); | 1356 | netif_stop_queue(dev); |
1356 | 1357 | ||
1357 | /* Disable port IRQ */ | ||
1358 | spin_lock_irq(&hw->hw_lock); | ||
1359 | hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | ||
1360 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1361 | spin_unlock_irq(&hw->hw_lock); | ||
1362 | |||
1363 | flush_scheduled_work(); | ||
1364 | |||
1365 | sky2_phy_reset(hw, port); | 1358 | sky2_phy_reset(hw, port); |
1366 | 1359 | ||
1367 | /* Stop transmitter */ | 1360 | /* Stop transmitter */ |
@@ -1405,6 +1398,11 @@ static int sky2_down(struct net_device *dev) | |||
1405 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | 1398 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); |
1406 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | 1399 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); |
1407 | 1400 | ||
1401 | /* Disable port IRQ */ | ||
1402 | imask = sky2_read32(hw, B0_IMSK); | ||
1403 | imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | ||
1404 | sky2_write32(hw, B0_IMSK, imask); | ||
1405 | |||
1408 | /* turn off LED's */ | 1406 | /* turn off LED's */ |
1409 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 1407 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
1410 | 1408 | ||
@@ -1599,20 +1597,19 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1599 | return 0; | 1597 | return 0; |
1600 | } | 1598 | } |
1601 | 1599 | ||
1602 | /* | 1600 | /* Interrupt from PHY */ |
1603 | * Interrupt from PHY are handled outside of interrupt context | 1601 | static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) |
1604 | * because accessing phy registers requires spin wait which might | ||
1605 | * cause excess interrupt latency. | ||
1606 | */ | ||
1607 | static void sky2_phy_task(void *arg) | ||
1608 | { | 1602 | { |
1609 | struct sky2_port *sky2 = arg; | 1603 | struct net_device *dev = hw->dev[port]; |
1610 | struct sky2_hw *hw = sky2->hw; | 1604 | struct sky2_port *sky2 = netdev_priv(dev); |
1611 | u16 istatus, phystat; | 1605 | u16 istatus, phystat; |
1612 | 1606 | ||
1613 | down(&sky2->phy_sema); | 1607 | spin_lock(&sky2->phy_lock); |
1614 | istatus = gm_phy_read(hw, sky2->port, PHY_MARV_INT_STAT); | 1608 | istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); |
1615 | phystat = gm_phy_read(hw, sky2->port, PHY_MARV_PHY_STAT); | 1609 | phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); |
1610 | |||
1611 | if (!netif_running(dev)) | ||
1612 | goto out; | ||
1616 | 1613 | ||
1617 | if (netif_msg_intr(sky2)) | 1614 | if (netif_msg_intr(sky2)) |
1618 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", | 1615 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", |
@@ -1638,12 +1635,7 @@ static void sky2_phy_task(void *arg) | |||
1638 | sky2_link_down(sky2); | 1635 | sky2_link_down(sky2); |
1639 | } | 1636 | } |
1640 | out: | 1637 | out: |
1641 | up(&sky2->phy_sema); | 1638 | spin_unlock(&sky2->phy_lock); |
1642 | |||
1643 | spin_lock_irq(&hw->hw_lock); | ||
1644 | hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; | ||
1645 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1646 | spin_unlock_irq(&hw->hw_lock); | ||
1647 | } | 1639 | } |
1648 | 1640 | ||
1649 | 1641 | ||
@@ -1655,20 +1647,6 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1655 | struct sky2_port *sky2 = netdev_priv(dev); | 1647 | struct sky2_port *sky2 = netdev_priv(dev); |
1656 | struct sky2_hw *hw = sky2->hw; | 1648 | struct sky2_hw *hw = sky2->hw; |
1657 | unsigned txq = txqaddr[sky2->port]; | 1649 | unsigned txq = txqaddr[sky2->port]; |
1658 | u16 ridx; | ||
1659 | |||
1660 | /* Maybe we just missed an status interrupt */ | ||
1661 | spin_lock(&sky2->tx_lock); | ||
1662 | ridx = sky2_read16(hw, | ||
1663 | sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); | ||
1664 | sky2_tx_complete(sky2, ridx); | ||
1665 | spin_unlock(&sky2->tx_lock); | ||
1666 | |||
1667 | if (!netif_queue_stopped(dev)) { | ||
1668 | if (net_ratelimit()) | ||
1669 | pr_info(PFX "transmit interrupt missed? recovered\n"); | ||
1670 | return; | ||
1671 | } | ||
1672 | 1650 | ||
1673 | if (netif_msg_timer(sky2)) | 1651 | if (netif_msg_timer(sky2)) |
1674 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); | 1652 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); |
@@ -1698,6 +1676,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1698 | struct sky2_hw *hw = sky2->hw; | 1676 | struct sky2_hw *hw = sky2->hw; |
1699 | int err; | 1677 | int err; |
1700 | u16 ctl, mode; | 1678 | u16 ctl, mode; |
1679 | u32 imask; | ||
1701 | 1680 | ||
1702 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | 1681 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) |
1703 | return -EINVAL; | 1682 | return -EINVAL; |
@@ -1710,12 +1689,15 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1710 | return 0; | 1689 | return 0; |
1711 | } | 1690 | } |
1712 | 1691 | ||
1692 | imask = sky2_read32(hw, B0_IMSK); | ||
1713 | sky2_write32(hw, B0_IMSK, 0); | 1693 | sky2_write32(hw, B0_IMSK, 0); |
1714 | 1694 | ||
1715 | dev->trans_start = jiffies; /* prevent tx timeout */ | 1695 | dev->trans_start = jiffies; /* prevent tx timeout */ |
1716 | netif_stop_queue(dev); | 1696 | netif_stop_queue(dev); |
1717 | netif_poll_disable(hw->dev[0]); | 1697 | netif_poll_disable(hw->dev[0]); |
1718 | 1698 | ||
1699 | synchronize_irq(hw->pdev->irq); | ||
1700 | |||
1719 | ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); | 1701 | ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); |
1720 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); | 1702 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); |
1721 | sky2_rx_stop(sky2); | 1703 | sky2_rx_stop(sky2); |
@@ -1734,7 +1716,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1734 | sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); | 1716 | sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); |
1735 | 1717 | ||
1736 | err = sky2_rx_start(sky2); | 1718 | err = sky2_rx_start(sky2); |
1737 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1719 | sky2_write32(hw, B0_IMSK, imask); |
1738 | 1720 | ||
1739 | if (err) | 1721 | if (err) |
1740 | dev_close(dev); | 1722 | dev_close(dev); |
@@ -1838,76 +1820,51 @@ error: | |||
1838 | goto resubmit; | 1820 | goto resubmit; |
1839 | } | 1821 | } |
1840 | 1822 | ||
1841 | /* | 1823 | /* Transmit complete */ |
1842 | * Check for transmit complete | 1824 | static inline void sky2_tx_done(struct net_device *dev, u16 last) |
1843 | */ | ||
1844 | #define TX_NO_STATUS 0xffff | ||
1845 | |||
1846 | static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last) | ||
1847 | { | 1825 | { |
1848 | if (last != TX_NO_STATUS) { | 1826 | struct sky2_port *sky2 = netdev_priv(dev); |
1849 | struct net_device *dev = hw->dev[port]; | ||
1850 | if (dev && netif_running(dev)) { | ||
1851 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1852 | 1827 | ||
1853 | spin_lock(&sky2->tx_lock); | 1828 | if (netif_running(dev)) { |
1854 | sky2_tx_complete(sky2, last); | 1829 | spin_lock(&sky2->tx_lock); |
1855 | spin_unlock(&sky2->tx_lock); | 1830 | sky2_tx_complete(sky2, last); |
1856 | } | 1831 | spin_unlock(&sky2->tx_lock); |
1857 | } | 1832 | } |
1858 | } | 1833 | } |
1859 | 1834 | ||
1860 | /* | 1835 | /* Process status response ring */ |
1861 | * Both ports share the same status interrupt, therefore there is only | 1836 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1862 | * one poll routine. | ||
1863 | */ | ||
1864 | static int sky2_poll(struct net_device *dev0, int *budget) | ||
1865 | { | 1837 | { |
1866 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 1838 | int work_done = 0; |
1867 | unsigned int to_do = min(dev0->quota, *budget); | ||
1868 | unsigned int work_done = 0; | ||
1869 | u16 hwidx; | ||
1870 | u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; | ||
1871 | |||
1872 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1873 | |||
1874 | /* | ||
1875 | * Kick the STAT_LEV_TIMER_CTRL timer. | ||
1876 | * This fixes my hangs on Yukon-EC (0xb6) rev 1. | ||
1877 | * The if clause is there to start the timer only if it has been | ||
1878 | * configured correctly and not been disabled via ethtool. | ||
1879 | */ | ||
1880 | if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) { | ||
1881 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP); | ||
1882 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); | ||
1883 | } | ||
1884 | 1839 | ||
1885 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1886 | BUG_ON(hwidx >= STATUS_RING_SIZE); | ||
1887 | rmb(); | 1840 | rmb(); |
1888 | 1841 | ||
1889 | while (hwidx != hw->st_idx) { | 1842 | for(;;) { |
1890 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1843 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
1891 | struct net_device *dev; | 1844 | struct net_device *dev; |
1892 | struct sky2_port *sky2; | 1845 | struct sky2_port *sky2; |
1893 | struct sk_buff *skb; | 1846 | struct sk_buff *skb; |
1894 | u32 status; | 1847 | u32 status; |
1895 | u16 length; | 1848 | u16 length; |
1849 | u8 link, opcode; | ||
1850 | |||
1851 | opcode = le->opcode; | ||
1852 | if (!opcode) | ||
1853 | break; | ||
1854 | opcode &= ~HW_OWNER; | ||
1896 | 1855 | ||
1897 | le = hw->st_le + hw->st_idx; | ||
1898 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; | 1856 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; |
1899 | prefetch(hw->st_le + hw->st_idx); | 1857 | le->opcode = 0; |
1900 | 1858 | ||
1901 | BUG_ON(le->link >= 2); | 1859 | link = le->link; |
1902 | dev = hw->dev[le->link]; | 1860 | BUG_ON(link >= 2); |
1903 | if (dev == NULL || !netif_running(dev)) | 1861 | dev = hw->dev[link]; |
1904 | continue; | ||
1905 | 1862 | ||
1906 | sky2 = netdev_priv(dev); | 1863 | sky2 = netdev_priv(dev); |
1907 | status = le32_to_cpu(le->status); | 1864 | length = le->length; |
1908 | length = le16_to_cpu(le->length); | 1865 | status = le->status; |
1909 | 1866 | ||
1910 | switch (le->opcode & ~HW_OWNER) { | 1867 | switch (opcode) { |
1911 | case OP_RXSTAT: | 1868 | case OP_RXSTAT: |
1912 | skb = sky2_receive(sky2, length, status); | 1869 | skb = sky2_receive(sky2, length, status); |
1913 | if (!skb) | 1870 | if (!skb) |
@@ -1947,42 +1904,23 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1947 | 1904 | ||
1948 | case OP_TXINDEXLE: | 1905 | case OP_TXINDEXLE: |
1949 | /* TX index reports status for both ports */ | 1906 | /* TX index reports status for both ports */ |
1950 | tx_done[0] = status & 0xffff; | 1907 | sky2_tx_done(hw->dev[0], status & 0xffff); |
1951 | tx_done[1] = ((status >> 24) & 0xff) | 1908 | if (hw->dev[1]) |
1952 | | (u16)(length & 0xf) << 8; | 1909 | sky2_tx_done(hw->dev[1], |
1910 | ((status >> 24) & 0xff) | ||
1911 | | (u16)(length & 0xf) << 8); | ||
1953 | break; | 1912 | break; |
1954 | 1913 | ||
1955 | default: | 1914 | default: |
1956 | if (net_ratelimit()) | 1915 | if (net_ratelimit()) |
1957 | printk(KERN_WARNING PFX | 1916 | printk(KERN_WARNING PFX |
1958 | "unknown status opcode 0x%x\n", le->opcode); | 1917 | "unknown status opcode 0x%x\n", opcode); |
1959 | break; | 1918 | break; |
1960 | } | 1919 | } |
1961 | } | 1920 | } |
1962 | 1921 | ||
1963 | exit_loop: | 1922 | exit_loop: |
1964 | sky2_tx_check(hw, 0, tx_done[0]); | 1923 | return work_done; |
1965 | sky2_tx_check(hw, 1, tx_done[1]); | ||
1966 | |||
1967 | if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { | ||
1968 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
1969 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
1970 | } | ||
1971 | |||
1972 | if (likely(work_done < to_do)) { | ||
1973 | spin_lock_irq(&hw->hw_lock); | ||
1974 | __netif_rx_complete(dev0); | ||
1975 | |||
1976 | hw->intr_mask |= Y2_IS_STAT_BMU; | ||
1977 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1978 | spin_unlock_irq(&hw->hw_lock); | ||
1979 | |||
1980 | return 0; | ||
1981 | } else { | ||
1982 | *budget -= work_done; | ||
1983 | dev0->quota -= work_done; | ||
1984 | return 1; | ||
1985 | } | ||
1986 | } | 1924 | } |
1987 | 1925 | ||
1988 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) | 1926 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) |
@@ -2101,42 +2039,17 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | |||
2101 | } | 2039 | } |
2102 | } | 2040 | } |
2103 | 2041 | ||
2104 | static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) | ||
2105 | { | ||
2106 | struct net_device *dev = hw->dev[port]; | ||
2107 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2108 | |||
2109 | hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | ||
2110 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
2111 | |||
2112 | schedule_work(&sky2->phy_task); | ||
2113 | } | ||
2114 | 2042 | ||
2115 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | 2043 | static int sky2_poll(struct net_device *dev0, int *budget) |
2116 | { | 2044 | { |
2117 | struct sky2_hw *hw = dev_id; | 2045 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
2118 | struct net_device *dev0 = hw->dev[0]; | 2046 | int work_limit = min(dev0->quota, *budget); |
2119 | u32 status; | 2047 | int work_done = 0; |
2120 | 2048 | u32 status = sky2_read32(hw, B0_ISRC); | |
2121 | status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
2122 | if (status == 0 || status == ~0) | ||
2123 | return IRQ_NONE; | ||
2124 | 2049 | ||
2125 | spin_lock(&hw->hw_lock); | ||
2126 | if (status & Y2_IS_HW_ERR) | 2050 | if (status & Y2_IS_HW_ERR) |
2127 | sky2_hw_intr(hw); | 2051 | sky2_hw_intr(hw); |
2128 | 2052 | ||
2129 | /* Do NAPI for Rx and Tx status */ | ||
2130 | if (status & Y2_IS_STAT_BMU) { | ||
2131 | hw->intr_mask &= ~Y2_IS_STAT_BMU; | ||
2132 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
2133 | |||
2134 | if (likely(__netif_rx_schedule_prep(dev0))) { | ||
2135 | prefetch(&hw->st_le[hw->st_idx]); | ||
2136 | __netif_rx_schedule(dev0); | ||
2137 | } | ||
2138 | } | ||
2139 | |||
2140 | if (status & Y2_IS_IRQ_PHY1) | 2053 | if (status & Y2_IS_IRQ_PHY1) |
2141 | sky2_phy_intr(hw, 0); | 2054 | sky2_phy_intr(hw, 0); |
2142 | 2055 | ||
@@ -2149,9 +2062,38 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2149 | if (status & Y2_IS_IRQ_MAC2) | 2062 | if (status & Y2_IS_IRQ_MAC2) |
2150 | sky2_mac_intr(hw, 1); | 2063 | sky2_mac_intr(hw, 1); |
2151 | 2064 | ||
2065 | if (status & Y2_IS_STAT_BMU) { | ||
2066 | work_done = sky2_status_intr(hw, work_limit); | ||
2067 | *budget -= work_done; | ||
2068 | dev0->quota -= work_done; | ||
2069 | |||
2070 | if (work_done >= work_limit) | ||
2071 | return 1; | ||
2072 | |||
2073 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
2074 | } | ||
2075 | |||
2076 | netif_rx_complete(dev0); | ||
2077 | |||
2078 | /* Ack interrupt and re-enable */ | ||
2152 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | 2079 | sky2_write32(hw, B0_Y2_SP_ICR, 2); |
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | ||
2084 | { | ||
2085 | struct sky2_hw *hw = dev_id; | ||
2086 | struct net_device *dev0 = hw->dev[0]; | ||
2087 | u32 status; | ||
2088 | |||
2089 | /* Reading this mask interrupts as side effect */ | ||
2090 | status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
2091 | if (status == 0 || status == ~0) | ||
2092 | return IRQ_NONE; | ||
2153 | 2093 | ||
2154 | spin_unlock(&hw->hw_lock); | 2094 | prefetch(&hw->st_le[hw->st_idx]); |
2095 | if (likely(__netif_rx_schedule_prep(dev0))) | ||
2096 | __netif_rx_schedule(dev0); | ||
2155 | 2097 | ||
2156 | return IRQ_HANDLED; | 2098 | return IRQ_HANDLED; |
2157 | } | 2099 | } |
@@ -2320,7 +2262,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2320 | /* Set the list last index */ | 2262 | /* Set the list last index */ |
2321 | sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); | 2263 | sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); |
2322 | 2264 | ||
2323 | /* These status setup values are copied from SysKonnect's driver */ | ||
2324 | sky2_write16(hw, STAT_TX_IDX_TH, 10); | 2265 | sky2_write16(hw, STAT_TX_IDX_TH, 10); |
2325 | sky2_write8(hw, STAT_FIFO_WM, 16); | 2266 | sky2_write8(hw, STAT_FIFO_WM, 16); |
2326 | 2267 | ||
@@ -2714,7 +2655,7 @@ static int sky2_phys_id(struct net_device *dev, u32 data) | |||
2714 | ms = data * 1000; | 2655 | ms = data * 1000; |
2715 | 2656 | ||
2716 | /* save initial values */ | 2657 | /* save initial values */ |
2717 | down(&sky2->phy_sema); | 2658 | spin_lock_bh(&sky2->phy_lock); |
2718 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | 2659 | if (hw->chip_id == CHIP_ID_YUKON_XL) { |
2719 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 2660 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
2720 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 2661 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); |
@@ -2730,9 +2671,9 @@ static int sky2_phys_id(struct net_device *dev, u32 data) | |||
2730 | sky2_led(hw, port, onoff); | 2671 | sky2_led(hw, port, onoff); |
2731 | onoff = !onoff; | 2672 | onoff = !onoff; |
2732 | 2673 | ||
2733 | up(&sky2->phy_sema); | 2674 | spin_unlock_bh(&sky2->phy_lock); |
2734 | interrupted = msleep_interruptible(250); | 2675 | interrupted = msleep_interruptible(250); |
2735 | down(&sky2->phy_sema); | 2676 | spin_lock_bh(&sky2->phy_lock); |
2736 | 2677 | ||
2737 | ms -= 250; | 2678 | ms -= 250; |
2738 | } | 2679 | } |
@@ -2747,7 +2688,7 @@ static int sky2_phys_id(struct net_device *dev, u32 data) | |||
2747 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 2688 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); |
2748 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | 2689 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); |
2749 | } | 2690 | } |
2750 | up(&sky2->phy_sema); | 2691 | spin_unlock_bh(&sky2->phy_lock); |
2751 | 2692 | ||
2752 | return 0; | 2693 | return 0; |
2753 | } | 2694 | } |
@@ -3023,8 +2964,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3023 | */ | 2964 | */ |
3024 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | 2965 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); |
3025 | 2966 | ||
3026 | INIT_WORK(&sky2->phy_task, sky2_phy_task, sky2); | 2967 | spin_lock_init(&sky2->phy_lock); |
3027 | init_MUTEX(&sky2->phy_sema); | ||
3028 | sky2->tx_pending = TX_DEF_PENDING; | 2968 | sky2->tx_pending = TX_DEF_PENDING; |
3029 | sky2->rx_pending = RX_DEF_PENDING; | 2969 | sky2->rx_pending = RX_DEF_PENDING; |
3030 | sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN); | 2970 | sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN); |
@@ -3136,7 +3076,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3136 | goto err_out_free_hw; | 3076 | goto err_out_free_hw; |
3137 | } | 3077 | } |
3138 | hw->pm_cap = pm_cap; | 3078 | hw->pm_cap = pm_cap; |
3139 | spin_lock_init(&hw->hw_lock); | ||
3140 | 3079 | ||
3141 | #ifdef __BIG_ENDIAN | 3080 | #ifdef __BIG_ENDIAN |
3142 | /* byte swap descriptors in hardware */ | 3081 | /* byte swap descriptors in hardware */ |
@@ -3196,8 +3135,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3196 | goto err_out_unregister; | 3135 | goto err_out_unregister; |
3197 | } | 3136 | } |
3198 | 3137 | ||
3199 | hw->intr_mask = Y2_IS_BASE; | 3138 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3200 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
3201 | 3139 | ||
3202 | pci_set_drvdata(pdev, hw); | 3140 | pci_set_drvdata(pdev, hw); |
3203 | 3141 | ||