diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 75 |
1 files changed, 29 insertions, 46 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 104e20456e6f..adfbe81693a6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/if_vlan.h> | 40 | #include <linux/if_vlan.h> |
41 | #include <linux/prefetch.h> | 41 | #include <linux/prefetch.h> |
42 | #include <linux/mii.h> | 42 | #include <linux/mii.h> |
43 | #include <linux/dmi.h> | ||
44 | 43 | ||
45 | #include <asm/irq.h> | 44 | #include <asm/irq.h> |
46 | 45 | ||
@@ -151,8 +150,6 @@ static const char *yukon2_name[] = { | |||
151 | "FE", /* 0xb7 */ | 150 | "FE", /* 0xb7 */ |
152 | }; | 151 | }; |
153 | 152 | ||
154 | static int dmi_blacklisted; | ||
155 | |||
156 | /* Access to external PHY */ | 153 | /* Access to external PHY */ |
157 | static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) | 154 | static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) |
158 | { | 155 | { |
@@ -307,10 +304,13 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
307 | PHY_M_EC_MAC_S_MSK); | 304 | PHY_M_EC_MAC_S_MSK); |
308 | ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); | 305 | ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); |
309 | 306 | ||
307 | /* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */ | ||
310 | if (hw->chip_id == CHIP_ID_YUKON_EC) | 308 | if (hw->chip_id == CHIP_ID_YUKON_EC) |
309 | /* set downshift counter to 3x and enable downshift */ | ||
311 | ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA; | 310 | ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA; |
312 | else | 311 | else |
313 | ectrl |= PHY_M_EC_M_DSC(2) | PHY_M_EC_S_DSC(3); | 312 | /* set master & slave downshift counter to 1x */ |
313 | ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); | ||
314 | 314 | ||
315 | gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); | 315 | gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); |
316 | } | 316 | } |
@@ -327,10 +327,12 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
327 | /* enable automatic crossover */ | 327 | /* enable automatic crossover */ |
328 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); | 328 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); |
329 | 329 | ||
330 | /* downshift on PHY 88E1112 and 88E1149 is changed */ | ||
330 | if (sky2->autoneg == AUTONEG_ENABLE | 331 | if (sky2->autoneg == AUTONEG_ENABLE |
331 | && (hw->chip_id == CHIP_ID_YUKON_XL | 332 | && (hw->chip_id == CHIP_ID_YUKON_XL |
332 | || hw->chip_id == CHIP_ID_YUKON_EC_U | 333 | || hw->chip_id == CHIP_ID_YUKON_EC_U |
333 | || hw->chip_id == CHIP_ID_YUKON_EX)) { | 334 | || hw->chip_id == CHIP_ID_YUKON_EX)) { |
335 | /* set downshift counter to 3x and enable downshift */ | ||
334 | ctrl &= ~PHY_M_PC_DSC_MSK; | 336 | ctrl &= ~PHY_M_PC_DSC_MSK; |
335 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | 337 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; |
336 | } | 338 | } |
@@ -362,7 +364,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
362 | /* for SFP-module set SIGDET polarity to low */ | 364 | /* for SFP-module set SIGDET polarity to low */ |
363 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | 365 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); |
364 | ctrl |= PHY_M_FIB_SIGD_POL; | 366 | ctrl |= PHY_M_FIB_SIGD_POL; |
365 | gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); | 367 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); |
366 | } | 368 | } |
367 | 369 | ||
368 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 370 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
@@ -656,7 +658,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
656 | const u8 *addr = hw->dev[port]->dev_addr; | 658 | const u8 *addr = hw->dev[port]->dev_addr; |
657 | 659 | ||
658 | sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | 660 | sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); |
659 | sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR|GPC_ENA_PAUSE); | 661 | sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); |
660 | 662 | ||
661 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); | 663 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); |
662 | 664 | ||
@@ -842,10 +844,12 @@ static inline struct tx_ring_info *tx_le_re(struct sky2_port *sky2, | |||
842 | /* Update chip's next pointer */ | 844 | /* Update chip's next pointer */ |
843 | static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) | 845 | static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) |
844 | { | 846 | { |
845 | q = Y2_QADDR(q, PREF_UNIT_PUT_IDX); | 847 | /* Make sure write' to descriptors are complete before we tell hardware */ |
846 | wmb(); | 848 | wmb(); |
847 | sky2_write16(hw, q, idx); | 849 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); |
848 | sky2_read16(hw, q); | 850 | |
851 | /* Synchronize I/O on since next processor may write to tail */ | ||
852 | mmiowb(); | ||
849 | } | 853 | } |
850 | 854 | ||
851 | 855 | ||
@@ -977,6 +981,7 @@ stopped: | |||
977 | 981 | ||
978 | /* reset the Rx prefetch unit */ | 982 | /* reset the Rx prefetch unit */ |
979 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 983 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); |
984 | mmiowb(); | ||
980 | } | 985 | } |
981 | 986 | ||
982 | /* Clean out receive buffer area, assumes receiver hardware stopped */ | 987 | /* Clean out receive buffer area, assumes receiver hardware stopped */ |
@@ -1196,7 +1201,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
1196 | } | 1201 | } |
1197 | 1202 | ||
1198 | /* Tell chip about available buffers */ | 1203 | /* Tell chip about available buffers */ |
1199 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 1204 | sky2_put_idx(hw, rxq, sky2->rx_put); |
1200 | return 0; | 1205 | return 0; |
1201 | nomem: | 1206 | nomem: |
1202 | sky2_rx_clean(sky2); | 1207 | sky2_rx_clean(sky2); |
@@ -1427,7 +1432,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1427 | tcpsum = offset << 16; /* sum start */ | 1432 | tcpsum = offset << 16; /* sum start */ |
1428 | tcpsum |= offset + skb->csum_offset; /* sum write */ | 1433 | tcpsum |= offset + skb->csum_offset; /* sum write */ |
1429 | 1434 | ||
1430 | ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; | 1435 | ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; |
1431 | if (ip_hdr(skb)->protocol == IPPROTO_UDP) | 1436 | if (ip_hdr(skb)->protocol == IPPROTO_UDP) |
1432 | ctrl |= UDPTCP; | 1437 | ctrl |= UDPTCP; |
1433 | 1438 | ||
@@ -1538,6 +1543,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1538 | } | 1543 | } |
1539 | 1544 | ||
1540 | sky2->tx_cons = idx; | 1545 | sky2->tx_cons = idx; |
1546 | smp_mb(); | ||
1547 | |||
1541 | if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) | 1548 | if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) |
1542 | netif_wake_queue(dev); | 1549 | netif_wake_queue(dev); |
1543 | } | 1550 | } |
@@ -1577,13 +1584,6 @@ static int sky2_down(struct net_device *dev) | |||
1577 | imask &= ~portirq_msk[port]; | 1584 | imask &= ~portirq_msk[port]; |
1578 | sky2_write32(hw, B0_IMSK, imask); | 1585 | sky2_write32(hw, B0_IMSK, imask); |
1579 | 1586 | ||
1580 | /* | ||
1581 | * Both ports share the NAPI poll on port 0, so if necessary undo the | ||
1582 | * the disable that is done in dev_close. | ||
1583 | */ | ||
1584 | if (sky2->port == 0 && hw->ports > 1) | ||
1585 | netif_poll_enable(dev); | ||
1586 | |||
1587 | sky2_gmac_reset(hw, port); | 1587 | sky2_gmac_reset(hw, port); |
1588 | 1588 | ||
1589 | /* Stop transmitter */ | 1589 | /* Stop transmitter */ |
@@ -2139,8 +2139,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
2139 | switch (le->opcode & ~HW_OWNER) { | 2139 | switch (le->opcode & ~HW_OWNER) { |
2140 | case OP_RXSTAT: | 2140 | case OP_RXSTAT: |
2141 | skb = sky2_receive(dev, length, status); | 2141 | skb = sky2_receive(dev, length, status); |
2142 | if (!skb) | 2142 | if (unlikely(!skb)) { |
2143 | sky2->net_stats.rx_dropped++; | ||
2143 | goto force_update; | 2144 | goto force_update; |
2145 | } | ||
2144 | 2146 | ||
2145 | skb->protocol = eth_type_trans(skb, dev); | 2147 | skb->protocol = eth_type_trans(skb, dev); |
2146 | sky2->net_stats.rx_packets++; | 2148 | sky2->net_stats.rx_packets++; |
@@ -2221,6 +2223,7 @@ force_update: | |||
2221 | 2223 | ||
2222 | /* Fully processed status ring so clear irq */ | 2224 | /* Fully processed status ring so clear irq */ |
2223 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2225 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2226 | mmiowb(); | ||
2224 | 2227 | ||
2225 | exit_loop: | 2228 | exit_loop: |
2226 | if (buf_write[0]) { | 2229 | if (buf_write[0]) { |
@@ -2341,6 +2344,12 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | |||
2341 | printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n", | 2344 | printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n", |
2342 | dev->name, status); | 2345 | dev->name, status); |
2343 | 2346 | ||
2347 | if (status & GM_IS_RX_CO_OV) | ||
2348 | gma_read16(hw, port, GM_RX_IRQ_SRC); | ||
2349 | |||
2350 | if (status & GM_IS_TX_CO_OV) | ||
2351 | gma_read16(hw, port, GM_TX_IRQ_SRC); | ||
2352 | |||
2344 | if (status & GM_IS_RX_FF_OR) { | 2353 | if (status & GM_IS_RX_FF_OR) { |
2345 | ++sky2->net_stats.rx_fifo_errors; | 2354 | ++sky2->net_stats.rx_fifo_errors; |
2346 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); | 2355 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); |
@@ -2439,6 +2448,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2439 | if (work_done < work_limit) { | 2448 | if (work_done < work_limit) { |
2440 | netif_rx_complete(dev0); | 2449 | netif_rx_complete(dev0); |
2441 | 2450 | ||
2451 | /* end of interrupt, re-enables also acts as I/O synchronization */ | ||
2442 | sky2_read32(hw, B0_Y2_SP_LISR); | 2452 | sky2_read32(hw, B0_Y2_SP_LISR); |
2443 | return 0; | 2453 | return 0; |
2444 | } else { | 2454 | } else { |
@@ -2534,17 +2544,6 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2534 | return -EOPNOTSUPP; | 2544 | return -EOPNOTSUPP; |
2535 | } | 2545 | } |
2536 | 2546 | ||
2537 | |||
2538 | /* Some Gigabyte motherboards have 88e8056 but cause problems | ||
2539 | * There is some unresolved hardware related problem that causes | ||
2540 | * descriptor errors and receive data corruption. | ||
2541 | */ | ||
2542 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && dmi_blacklisted) { | ||
2543 | dev_err(&hw->pdev->dev, | ||
2544 | "88E8056 on this motherboard not supported\n"); | ||
2545 | return -EOPNOTSUPP; | ||
2546 | } | ||
2547 | |||
2548 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); | 2547 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); |
2549 | hw->ports = 1; | 2548 | hw->ports = 1; |
2550 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | 2549 | t8 = sky2_read8(hw, B2_Y2_HW_RES); |
@@ -3910,24 +3909,8 @@ static struct pci_driver sky2_driver = { | |||
3910 | .shutdown = sky2_shutdown, | 3909 | .shutdown = sky2_shutdown, |
3911 | }; | 3910 | }; |
3912 | 3911 | ||
3913 | static struct dmi_system_id __initdata broken_dmi_table[] = { | ||
3914 | { | ||
3915 | .ident = "Gigabyte 965P-S3", | ||
3916 | .matches = { | ||
3917 | DMI_MATCH(DMI_SYS_VENDOR, "Gigabyte Technology Co., Ltd."), | ||
3918 | DMI_MATCH(DMI_PRODUCT_NAME, "965P-S3"), | ||
3919 | |||
3920 | }, | ||
3921 | }, | ||
3922 | { } | ||
3923 | }; | ||
3924 | |||
3925 | static int __init sky2_init_module(void) | 3912 | static int __init sky2_init_module(void) |
3926 | { | 3913 | { |
3927 | /* Look for sick motherboards */ | ||
3928 | if (dmi_check_system(broken_dmi_table)) | ||
3929 | dmi_blacklisted = 1; | ||
3930 | |||
3931 | return pci_register_driver(&sky2_driver); | 3914 | return pci_register_driver(&sky2_driver); |
3932 | } | 3915 | } |
3933 | 3916 | ||