diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index eaffe551d1d8..162489b9f599 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -338,6 +338,16 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
338 | if (!(hw->flags & SKY2_HW_GIGABIT)) { | 338 | if (!(hw->flags & SKY2_HW_GIGABIT)) { |
339 | /* enable automatic crossover */ | 339 | /* enable automatic crossover */ |
340 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; | 340 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; |
341 | |||
342 | if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
343 | hw->chip_rev == CHIP_REV_YU_FE2_A0) { | ||
344 | u16 spec; | ||
345 | |||
346 | /* Enable Class A driver for FE+ A0 */ | ||
347 | spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2); | ||
348 | spec |= PHY_M_FESC_SEL_CL_A; | ||
349 | gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); | ||
350 | } | ||
341 | } else { | 351 | } else { |
342 | /* disable energy detect */ | 352 | /* disable energy detect */ |
343 | ctrl &= ~PHY_M_PC_EN_DET_MSK; | 353 | ctrl &= ~PHY_M_PC_EN_DET_MSK; |
@@ -816,7 +826,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
816 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); | 826 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); |
817 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); | 827 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); |
818 | 828 | ||
819 | if (!(hw->flags & SKY2_HW_RAMBUFFER)) { | 829 | /* On chips without ram buffer, pause is controled by MAC level */ |
830 | if (sky2_read8(hw, B2_E_0) == 0) { | ||
820 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); | 831 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); |
821 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); | 832 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); |
822 | 833 | ||
@@ -899,6 +910,20 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | |||
899 | return le; | 910 | return le; |
900 | } | 911 | } |
901 | 912 | ||
913 | static void tx_init(struct sky2_port *sky2) | ||
914 | { | ||
915 | struct sky2_tx_le *le; | ||
916 | |||
917 | sky2->tx_prod = sky2->tx_cons = 0; | ||
918 | sky2->tx_tcpsum = 0; | ||
919 | sky2->tx_last_mss = 0; | ||
920 | |||
921 | le = get_tx_le(sky2); | ||
922 | le->addr = 0; | ||
923 | le->opcode = OP_ADDR64 | HW_OWNER; | ||
924 | sky2->tx_addr64 = 0; | ||
925 | } | ||
926 | |||
902 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, | 927 | static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, |
903 | struct sky2_tx_le *le) | 928 | struct sky2_tx_le *le) |
904 | { | 929 | { |
@@ -1271,7 +1296,7 @@ static int sky2_up(struct net_device *dev) | |||
1271 | struct sky2_port *sky2 = netdev_priv(dev); | 1296 | struct sky2_port *sky2 = netdev_priv(dev); |
1272 | struct sky2_hw *hw = sky2->hw; | 1297 | struct sky2_hw *hw = sky2->hw; |
1273 | unsigned port = sky2->port; | 1298 | unsigned port = sky2->port; |
1274 | u32 imask; | 1299 | u32 imask, ramsize; |
1275 | int cap, err = -ENOMEM; | 1300 | int cap, err = -ENOMEM; |
1276 | struct net_device *otherdev = hw->dev[sky2->port^1]; | 1301 | struct net_device *otherdev = hw->dev[sky2->port^1]; |
1277 | 1302 | ||
@@ -1309,7 +1334,8 @@ static int sky2_up(struct net_device *dev) | |||
1309 | GFP_KERNEL); | 1334 | GFP_KERNEL); |
1310 | if (!sky2->tx_ring) | 1335 | if (!sky2->tx_ring) |
1311 | goto err_out; | 1336 | goto err_out; |
1312 | sky2->tx_prod = sky2->tx_cons = 0; | 1337 | |
1338 | tx_init(sky2); | ||
1313 | 1339 | ||
1314 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, | 1340 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, |
1315 | &sky2->rx_le_map); | 1341 | &sky2->rx_le_map); |
@@ -1326,13 +1352,12 @@ static int sky2_up(struct net_device *dev) | |||
1326 | 1352 | ||
1327 | sky2_mac_init(hw, port); | 1353 | sky2_mac_init(hw, port); |
1328 | 1354 | ||
1329 | if (hw->flags & SKY2_HW_RAMBUFFER) { | 1355 | /* Register is number of 4K blocks on internal RAM buffer. */ |
1330 | /* Register is number of 4K blocks on internal RAM buffer. */ | 1356 | ramsize = sky2_read8(hw, B2_E_0) * 4; |
1331 | u32 ramsize = sky2_read8(hw, B2_E_0) * 4; | 1357 | if (ramsize > 0) { |
1332 | u32 rxspace; | 1358 | u32 rxspace; |
1333 | 1359 | ||
1334 | printk(KERN_DEBUG PFX "%s: ram buffer %dK\n", dev->name, ramsize); | 1360 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); |
1335 | |||
1336 | if (ramsize < 16) | 1361 | if (ramsize < 16) |
1337 | rxspace = ramsize / 2; | 1362 | rxspace = ramsize / 2; |
1338 | else | 1363 | else |
@@ -1995,7 +2020,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1995 | 2020 | ||
1996 | synchronize_irq(hw->pdev->irq); | 2021 | synchronize_irq(hw->pdev->irq); |
1997 | 2022 | ||
1998 | if (!(hw->flags & SKY2_HW_RAMBUFFER)) | 2023 | if (sky2_read8(hw, B2_E_0) == 0) |
1999 | sky2_set_tx_stfwd(hw, port); | 2024 | sky2_set_tx_stfwd(hw, port); |
2000 | 2025 | ||
2001 | ctl = gma_read16(hw, port, GM_GP_CTRL); | 2026 | ctl = gma_read16(hw, port, GM_GP_CTRL); |
@@ -2138,6 +2163,18 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2138 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; | 2163 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; |
2139 | prefetch(sky2->rx_ring + sky2->rx_next); | 2164 | prefetch(sky2->rx_ring + sky2->rx_next); |
2140 | 2165 | ||
2166 | if (length < ETH_ZLEN || length > sky2->rx_data_size) | ||
2167 | goto len_error; | ||
2168 | |||
2169 | /* This chip has hardware problems that generates bogus status. | ||
2170 | * So do only marginal checking and expect higher level protocols | ||
2171 | * to handle crap frames. | ||
2172 | */ | ||
2173 | if (sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
2174 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0 && | ||
2175 | length != count) | ||
2176 | goto okay; | ||
2177 | |||
2141 | if (status & GMR_FS_ANY_ERR) | 2178 | if (status & GMR_FS_ANY_ERR) |
2142 | goto error; | 2179 | goto error; |
2143 | 2180 | ||
@@ -2146,8 +2183,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
2146 | 2183 | ||
2147 | /* if length reported by DMA does not match PHY, packet was truncated */ | 2184 | /* if length reported by DMA does not match PHY, packet was truncated */ |
2148 | if (length != count) | 2185 | if (length != count) |
2149 | goto len_mismatch; | 2186 | goto len_error; |
2150 | 2187 | ||
2188 | okay: | ||
2151 | if (length < copybreak) | 2189 | if (length < copybreak) |
2152 | skb = receive_copy(sky2, re, length); | 2190 | skb = receive_copy(sky2, re, length); |
2153 | else | 2191 | else |
@@ -2157,13 +2195,13 @@ resubmit: | |||
2157 | 2195 | ||
2158 | return skb; | 2196 | return skb; |
2159 | 2197 | ||
2160 | len_mismatch: | 2198 | len_error: |
2161 | /* Truncation of overlength packets | 2199 | /* Truncation of overlength packets |
2162 | causes PHY length to not match MAC length */ | 2200 | causes PHY length to not match MAC length */ |
2163 | ++sky2->net_stats.rx_length_errors; | 2201 | ++sky2->net_stats.rx_length_errors; |
2164 | if (netif_msg_rx_err(sky2) && net_ratelimit()) | 2202 | if (netif_msg_rx_err(sky2) && net_ratelimit()) |
2165 | pr_info(PFX "%s: rx length mismatch: length %d status %#x\n", | 2203 | pr_info(PFX "%s: rx length error: status %#x length %d\n", |
2166 | dev->name, length, status); | 2204 | dev->name, status, length); |
2167 | goto resubmit; | 2205 | goto resubmit; |
2168 | 2206 | ||
2169 | error: | 2207 | error: |
@@ -2526,7 +2564,7 @@ static void sky2_watchdog(unsigned long arg) | |||
2526 | ++active; | 2564 | ++active; |
2527 | 2565 | ||
2528 | /* For chips with Rx FIFO, check if stuck */ | 2566 | /* For chips with Rx FIFO, check if stuck */ |
2529 | if ((hw->flags & SKY2_HW_RAMBUFFER) && | 2567 | if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) && |
2530 | sky2_rx_hung(dev)) { | 2568 | sky2_rx_hung(dev)) { |
2531 | pr_info(PFX "%s: receiver hang detected\n", | 2569 | pr_info(PFX "%s: receiver hang detected\n", |
2532 | dev->name); | 2570 | dev->name); |
@@ -2684,8 +2722,10 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2684 | switch(hw->chip_id) { | 2722 | switch(hw->chip_id) { |
2685 | case CHIP_ID_YUKON_XL: | 2723 | case CHIP_ID_YUKON_XL: |
2686 | hw->flags = SKY2_HW_GIGABIT | 2724 | hw->flags = SKY2_HW_GIGABIT |
2687 | | SKY2_HW_NEWER_PHY | 2725 | | SKY2_HW_NEWER_PHY; |
2688 | | SKY2_HW_RAMBUFFER; | 2726 | if (hw->chip_rev < 3) |
2727 | hw->flags |= SKY2_HW_FIFO_HANG_CHECK; | ||
2728 | |||
2689 | break; | 2729 | break; |
2690 | 2730 | ||
2691 | case CHIP_ID_YUKON_EC_U: | 2731 | case CHIP_ID_YUKON_EC_U: |
@@ -2711,11 +2751,10 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2711 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); | 2751 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); |
2712 | return -EOPNOTSUPP; | 2752 | return -EOPNOTSUPP; |
2713 | } | 2753 | } |
2714 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RAMBUFFER; | 2754 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK; |
2715 | break; | 2755 | break; |
2716 | 2756 | ||
2717 | case CHIP_ID_YUKON_FE: | 2757 | case CHIP_ID_YUKON_FE: |
2718 | hw->flags = SKY2_HW_RAMBUFFER; | ||
2719 | break; | 2758 | break; |
2720 | 2759 | ||
2721 | case CHIP_ID_YUKON_FE_P: | 2760 | case CHIP_ID_YUKON_FE_P: |
@@ -3923,13 +3962,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3923 | sky2->hw = hw; | 3962 | sky2->hw = hw; |
3924 | sky2->msg_enable = netif_msg_init(debug, default_msg); | 3963 | sky2->msg_enable = netif_msg_init(debug, default_msg); |
3925 | 3964 | ||
3926 | /* This chip has hardware problems that generates | ||
3927 | * bogus PHY receive status so by default shut up the message. | ||
3928 | */ | ||
3929 | if (hw->chip_id == CHIP_ID_YUKON_FE_P && | ||
3930 | hw->chip_rev == CHIP_REV_YU_FE2_A0) | ||
3931 | sky2->msg_enable &= ~NETIF_MSG_RX_ERR; | ||
3932 | |||
3933 | /* Auto speed and flow control */ | 3965 | /* Auto speed and flow control */ |
3934 | sky2->autoneg = AUTONEG_ENABLE; | 3966 | sky2->autoneg = AUTONEG_ENABLE; |
3935 | sky2->flow_mode = FC_BOTH; | 3967 | sky2->flow_mode = FC_BOTH; |
@@ -3953,8 +3985,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3953 | dev->features |= NETIF_F_HIGHDMA; | 3985 | dev->features |= NETIF_F_HIGHDMA; |
3954 | 3986 | ||
3955 | #ifdef SKY2_VLAN_TAG_USED | 3987 | #ifdef SKY2_VLAN_TAG_USED |
3956 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 3988 | /* The workaround for FE+ status conflicts with VLAN tag detection. */ |
3957 | dev->vlan_rx_register = sky2_vlan_rx_register; | 3989 | if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && |
3990 | sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) { | ||
3991 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
3992 | dev->vlan_rx_register = sky2_vlan_rx_register; | ||
3993 | } | ||
3958 | #endif | 3994 | #endif |
3959 | 3995 | ||
3960 | /* read the mac address */ | 3996 | /* read the mac address */ |