diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 125 |
1 files changed, 82 insertions, 43 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f2ab3d56e565..52edbd7ac17e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include "sky2.h" | 49 | #include "sky2.h" |
50 | 50 | ||
51 | #define DRV_NAME "sky2" | 51 | #define DRV_NAME "sky2" |
52 | #define DRV_VERSION "1.12" | 52 | #define DRV_VERSION "1.13" |
53 | #define PFX DRV_NAME " " | 53 | #define PFX DRV_NAME " " |
54 | 54 | ||
55 | /* | 55 | /* |
@@ -1742,13 +1742,6 @@ static void sky2_link_down(struct sky2_port *sky2) | |||
1742 | reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); | 1742 | reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); |
1743 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1743 | gma_write16(hw, port, GM_GP_CTRL, reg); |
1744 | 1744 | ||
1745 | if (sky2->flow_status == FC_RX) { | ||
1746 | /* restore Asymmetric Pause bit */ | ||
1747 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, | ||
1748 | gm_phy_read(hw, port, PHY_MARV_AUNE_ADV) | ||
1749 | | PHY_M_AN_ASP); | ||
1750 | } | ||
1751 | |||
1752 | netif_carrier_off(sky2->netdev); | 1745 | netif_carrier_off(sky2->netdev); |
1753 | netif_stop_queue(sky2->netdev); | 1746 | netif_stop_queue(sky2->netdev); |
1754 | 1747 | ||
@@ -1773,10 +1766,10 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1773 | { | 1766 | { |
1774 | struct sky2_hw *hw = sky2->hw; | 1767 | struct sky2_hw *hw = sky2->hw; |
1775 | unsigned port = sky2->port; | 1768 | unsigned port = sky2->port; |
1776 | u16 lpa; | 1769 | u16 advert, lpa; |
1777 | 1770 | ||
1771 | advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); | ||
1778 | lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP); | 1772 | lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP); |
1779 | |||
1780 | if (lpa & PHY_M_AN_RF) { | 1773 | if (lpa & PHY_M_AN_RF) { |
1781 | printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name); | 1774 | printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name); |
1782 | return -1; | 1775 | return -1; |
@@ -1791,20 +1784,40 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1791 | sky2->speed = sky2_phy_speed(hw, aux); | 1784 | sky2->speed = sky2_phy_speed(hw, aux); |
1792 | sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; | 1785 | sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; |
1793 | 1786 | ||
1794 | /* Pause bits are offset (9..8) */ | 1787 | /* Since the pause result bits seem to in different positions on |
1795 | if (hw->chip_id == CHIP_ID_YUKON_XL | 1788 | * different chips. look at registers. |
1796 | || hw->chip_id == CHIP_ID_YUKON_EC_U | 1789 | */ |
1797 | || hw->chip_id == CHIP_ID_YUKON_EX) | 1790 | if (!sky2_is_copper(hw)) { |
1798 | aux >>= 6; | 1791 | /* Shift for bits in fiber PHY */ |
1799 | 1792 | advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); | |
1800 | sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN, | 1793 | lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); |
1801 | aux & PHY_M_PS_TX_P_EN); | 1794 | |
1795 | if (advert & ADVERTISE_1000XPAUSE) | ||
1796 | advert |= ADVERTISE_PAUSE_CAP; | ||
1797 | if (advert & ADVERTISE_1000XPSE_ASYM) | ||
1798 | advert |= ADVERTISE_PAUSE_ASYM; | ||
1799 | if (lpa & LPA_1000XPAUSE) | ||
1800 | lpa |= LPA_PAUSE_CAP; | ||
1801 | if (lpa & LPA_1000XPAUSE_ASYM) | ||
1802 | lpa |= LPA_PAUSE_ASYM; | ||
1803 | } | ||
1804 | |||
1805 | sky2->flow_status = FC_NONE; | ||
1806 | if (advert & ADVERTISE_PAUSE_CAP) { | ||
1807 | if (lpa & LPA_PAUSE_CAP) | ||
1808 | sky2->flow_status = FC_BOTH; | ||
1809 | else if (advert & ADVERTISE_PAUSE_ASYM) | ||
1810 | sky2->flow_status = FC_RX; | ||
1811 | } else if (advert & ADVERTISE_PAUSE_ASYM) { | ||
1812 | if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM)) | ||
1813 | sky2->flow_status = FC_TX; | ||
1814 | } | ||
1802 | 1815 | ||
1803 | if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 | 1816 | if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 |
1804 | && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)) | 1817 | && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)) |
1805 | sky2->flow_status = FC_NONE; | 1818 | sky2->flow_status = FC_NONE; |
1806 | 1819 | ||
1807 | if (aux & PHY_M_PS_RX_P_EN) | 1820 | if (sky2->flow_status & FC_TX) |
1808 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); | 1821 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); |
1809 | else | 1822 | else |
1810 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | 1823 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); |
@@ -1853,16 +1866,13 @@ out: | |||
1853 | spin_unlock(&sky2->phy_lock); | 1866 | spin_unlock(&sky2->phy_lock); |
1854 | } | 1867 | } |
1855 | 1868 | ||
1856 | |||
1857 | /* Transmit timeout is only called if we are running, carrier is up | 1869 | /* Transmit timeout is only called if we are running, carrier is up |
1858 | * and tx queue is full (stopped). | 1870 | * and tx queue is full (stopped). |
1859 | * Called with netif_tx_lock held. | ||
1860 | */ | 1871 | */ |
1861 | static void sky2_tx_timeout(struct net_device *dev) | 1872 | static void sky2_tx_timeout(struct net_device *dev) |
1862 | { | 1873 | { |
1863 | struct sky2_port *sky2 = netdev_priv(dev); | 1874 | struct sky2_port *sky2 = netdev_priv(dev); |
1864 | struct sky2_hw *hw = sky2->hw; | 1875 | struct sky2_hw *hw = sky2->hw; |
1865 | u32 imask; | ||
1866 | 1876 | ||
1867 | if (netif_msg_timer(sky2)) | 1877 | if (netif_msg_timer(sky2)) |
1868 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); | 1878 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); |
@@ -1872,19 +1882,8 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1872 | sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), | 1882 | sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), |
1873 | sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); | 1883 | sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); |
1874 | 1884 | ||
1875 | imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */ | 1885 | /* can't restart safely under softirq */ |
1876 | sky2_write32(hw, B0_IMSK, 0); | 1886 | schedule_work(&hw->restart_work); |
1877 | sky2_read32(hw, B0_IMSK); | ||
1878 | |||
1879 | netif_poll_disable(hw->dev[0]); /* stop NAPI poll */ | ||
1880 | synchronize_irq(hw->pdev->irq); | ||
1881 | |||
1882 | netif_start_queue(dev); /* don't wakeup during flush */ | ||
1883 | sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */ | ||
1884 | |||
1885 | sky2_write32(hw, B0_IMSK, imask); | ||
1886 | |||
1887 | sky2_phy_reinit(sky2); /* this clears flow control etc */ | ||
1888 | } | 1887 | } |
1889 | 1888 | ||
1890 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1889 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -2057,9 +2056,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2057 | if (!(status & GMR_FS_RX_OK)) | 2056 | if (!(status & GMR_FS_RX_OK)) |
2058 | goto resubmit; | 2057 | goto resubmit; |
2059 | 2058 | ||
2060 | if (length > dev->mtu + ETH_HLEN) | ||
2061 | goto oversize; | ||
2062 | |||
2063 | if (length < copybreak) | 2059 | if (length < copybreak) |
2064 | skb = receive_copy(sky2, re, length); | 2060 | skb = receive_copy(sky2, re, length); |
2065 | else | 2061 | else |
@@ -2069,14 +2065,10 @@ resubmit: | |||
2069 | 2065 | ||
2070 | return skb; | 2066 | return skb; |
2071 | 2067 | ||
2072 | oversize: | ||
2073 | ++sky2->net_stats.rx_over_errors; | ||
2074 | goto resubmit; | ||
2075 | |||
2076 | error: | 2068 | error: |
2077 | ++sky2->net_stats.rx_errors; | 2069 | ++sky2->net_stats.rx_errors; |
2078 | if (status & GMR_FS_RX_FF_OV) { | 2070 | if (status & GMR_FS_RX_FF_OV) { |
2079 | sky2->net_stats.rx_fifo_errors++; | 2071 | sky2->net_stats.rx_over_errors++; |
2080 | goto resubmit; | 2072 | goto resubmit; |
2081 | } | 2073 | } |
2082 | 2074 | ||
@@ -2638,6 +2630,49 @@ static void sky2_reset(struct sky2_hw *hw) | |||
2638 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2630 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
2639 | } | 2631 | } |
2640 | 2632 | ||
2633 | static void sky2_restart(struct work_struct *work) | ||
2634 | { | ||
2635 | struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); | ||
2636 | struct net_device *dev; | ||
2637 | int i, err; | ||
2638 | |||
2639 | dev_dbg(&hw->pdev->dev, "restarting\n"); | ||
2640 | |||
2641 | del_timer_sync(&hw->idle_timer); | ||
2642 | |||
2643 | rtnl_lock(); | ||
2644 | sky2_write32(hw, B0_IMSK, 0); | ||
2645 | sky2_read32(hw, B0_IMSK); | ||
2646 | |||
2647 | netif_poll_disable(hw->dev[0]); | ||
2648 | |||
2649 | for (i = 0; i < hw->ports; i++) { | ||
2650 | dev = hw->dev[i]; | ||
2651 | if (netif_running(dev)) | ||
2652 | sky2_down(dev); | ||
2653 | } | ||
2654 | |||
2655 | sky2_reset(hw); | ||
2656 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | ||
2657 | netif_poll_enable(hw->dev[0]); | ||
2658 | |||
2659 | for (i = 0; i < hw->ports; i++) { | ||
2660 | dev = hw->dev[i]; | ||
2661 | if (netif_running(dev)) { | ||
2662 | err = sky2_up(dev); | ||
2663 | if (err) { | ||
2664 | printk(KERN_INFO PFX "%s: could not restart %d\n", | ||
2665 | dev->name, err); | ||
2666 | dev_close(dev); | ||
2667 | } | ||
2668 | } | ||
2669 | } | ||
2670 | |||
2671 | sky2_idle_start(hw); | ||
2672 | |||
2673 | rtnl_unlock(); | ||
2674 | } | ||
2675 | |||
2641 | static inline u8 sky2_wol_supported(const struct sky2_hw *hw) | 2676 | static inline u8 sky2_wol_supported(const struct sky2_hw *hw) |
2642 | { | 2677 | { |
2643 | return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; | 2678 | return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; |
@@ -3600,6 +3635,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3600 | } | 3635 | } |
3601 | 3636 | ||
3602 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | 3637 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); |
3638 | INIT_WORK(&hw->restart_work, sky2_restart); | ||
3639 | |||
3603 | sky2_idle_start(hw); | 3640 | sky2_idle_start(hw); |
3604 | 3641 | ||
3605 | pci_set_drvdata(pdev, hw); | 3642 | pci_set_drvdata(pdev, hw); |
@@ -3636,6 +3673,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3636 | 3673 | ||
3637 | del_timer_sync(&hw->idle_timer); | 3674 | del_timer_sync(&hw->idle_timer); |
3638 | 3675 | ||
3676 | flush_scheduled_work(); | ||
3677 | |||
3639 | sky2_write32(hw, B0_IMSK, 0); | 3678 | sky2_write32(hw, B0_IMSK, 0); |
3640 | synchronize_irq(hw->pdev->irq); | 3679 | synchronize_irq(hw->pdev->irq); |
3641 | 3680 | ||