diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-24 04:22:21 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-24 04:22:21 -0400 |
commit | 66643de455c27973ac31ad6de9f859d399916842 (patch) | |
tree | 7ebed7f051879007d4b11d6aaa9e65a1bcb0b08f /drivers/net/sky2.c | |
parent | 2c23d62abb820e19c54012520f08a198c2233a85 (diff) | |
parent | 387e2b0439026aa738a9edca15a57e5c0bcb4dfc (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
include/asm-powerpc/unistd.h
include/asm-sparc/unistd.h
include/asm-sparc64/unistd.h
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 257 |
1 files changed, 148 insertions, 109 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 227df9876a2c..60779ebf2ff6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "1.2" | 54 | #define DRV_VERSION "1.4" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -79,6 +79,8 @@ | |||
79 | #define NAPI_WEIGHT 64 | 79 | #define NAPI_WEIGHT 64 |
80 | #define PHY_RETRIES 1000 | 80 | #define PHY_RETRIES 1000 |
81 | 81 | ||
82 | #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) | ||
83 | |||
82 | static const u32 default_msg = | 84 | static const u32 default_msg = |
83 | NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | 85 | NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK |
84 | | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR | 86 | | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR |
@@ -96,9 +98,14 @@ static int disable_msi = 0; | |||
96 | module_param(disable_msi, int, 0); | 98 | module_param(disable_msi, int, 0); |
97 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | 99 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); |
98 | 100 | ||
101 | static int idle_timeout = 100; | ||
102 | module_param(idle_timeout, int, 0); | ||
103 | MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)"); | ||
104 | |||
99 | static const struct pci_device_id sky2_id_table[] = { | 105 | static const struct pci_device_id sky2_id_table[] = { |
100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
108 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ | ||
102 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, | 109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, |
103 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, | 110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, |
104 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, | 111 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, |
@@ -122,6 +129,7 @@ MODULE_DEVICE_TABLE(pci, sky2_id_table); | |||
122 | /* Avoid conditionals by using array */ | 129 | /* Avoid conditionals by using array */ |
123 | static const unsigned txqaddr[] = { Q_XA1, Q_XA2 }; | 130 | static const unsigned txqaddr[] = { Q_XA1, Q_XA2 }; |
124 | static const unsigned rxqaddr[] = { Q_R1, Q_R2 }; | 131 | static const unsigned rxqaddr[] = { Q_R1, Q_R2 }; |
132 | static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 }; | ||
125 | 133 | ||
126 | /* This driver supports yukon2 chipset only */ | 134 | /* This driver supports yukon2 chipset only */ |
127 | static const char *yukon2_name[] = { | 135 | static const char *yukon2_name[] = { |
@@ -228,6 +236,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
228 | } | 236 | } |
229 | 237 | ||
230 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | 238 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { |
239 | sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); | ||
231 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | 240 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); |
232 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); | 241 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); |
233 | reg1 &= P_ASPM_CONTROL_MSK; | 242 | reg1 &= P_ASPM_CONTROL_MSK; |
@@ -298,7 +307,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
298 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | 307 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); |
299 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; | 308 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; |
300 | 309 | ||
301 | if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) { | 310 | if (sky2->autoneg == AUTONEG_ENABLE && |
311 | !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { | ||
302 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 312 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
303 | 313 | ||
304 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | 314 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | |
@@ -326,7 +336,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
326 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); | 336 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); |
327 | 337 | ||
328 | if (sky2->autoneg == AUTONEG_ENABLE && | 338 | if (sky2->autoneg == AUTONEG_ENABLE && |
329 | hw->chip_id == CHIP_ID_YUKON_XL) { | 339 | (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { |
330 | ctrl &= ~PHY_M_PC_DSC_MSK; | 340 | ctrl &= ~PHY_M_PC_DSC_MSK; |
331 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | 341 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; |
332 | } | 342 | } |
@@ -442,10 +452,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
442 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 452 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); |
443 | 453 | ||
444 | /* set LED Function Control register */ | 454 | /* set LED Function Control register */ |
445 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | 455 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, |
446 | PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */ | 456 | (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ |
447 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ | 457 | PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */ |
448 | PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */ | 458 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ |
459 | PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */ | ||
449 | 460 | ||
450 | /* set Polarity Control register */ | 461 | /* set Polarity Control register */ |
451 | gm_phy_write(hw, port, PHY_MARV_PHY_STAT, | 462 | gm_phy_write(hw, port, PHY_MARV_PHY_STAT, |
@@ -459,6 +470,25 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
459 | /* restore page register */ | 470 | /* restore page register */ |
460 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 471 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
461 | break; | 472 | break; |
473 | case CHIP_ID_YUKON_EC_U: | ||
474 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
475 | |||
476 | /* select page 3 to access LED control register */ | ||
477 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
478 | |||
479 | /* set LED Function Control register */ | ||
480 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, | ||
481 | (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | ||
482 | PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */ | ||
483 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ | ||
484 | PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */ | ||
485 | |||
486 | /* set Blink Rate in LED Timer Control Register */ | ||
487 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, | ||
488 | ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS)); | ||
489 | /* restore page register */ | ||
490 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
491 | break; | ||
462 | 492 | ||
463 | default: | 493 | default: |
464 | /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ | 494 | /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ |
@@ -467,19 +497,21 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
467 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); | 497 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); |
468 | } | 498 | } |
469 | 499 | ||
470 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) { | 500 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) { |
471 | /* apply fixes in PHY AFE */ | 501 | /* apply fixes in PHY AFE */ |
472 | gm_phy_write(hw, port, 22, 255); | 502 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
503 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255); | ||
504 | |||
473 | /* increase differential signal amplitude in 10BASE-T */ | 505 | /* increase differential signal amplitude in 10BASE-T */ |
474 | gm_phy_write(hw, port, 24, 0xaa99); | 506 | gm_phy_write(hw, port, 0x18, 0xaa99); |
475 | gm_phy_write(hw, port, 23, 0x2011); | 507 | gm_phy_write(hw, port, 0x17, 0x2011); |
476 | 508 | ||
477 | /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ | 509 | /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ |
478 | gm_phy_write(hw, port, 24, 0xa204); | 510 | gm_phy_write(hw, port, 0x18, 0xa204); |
479 | gm_phy_write(hw, port, 23, 0x2002); | 511 | gm_phy_write(hw, port, 0x17, 0x2002); |
480 | 512 | ||
481 | /* set page register to 0 */ | 513 | /* set page register to 0 */ |
482 | gm_phy_write(hw, port, 22, 0); | 514 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
483 | } else { | 515 | } else { |
484 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 516 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); |
485 | 517 | ||
@@ -553,6 +585,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
553 | 585 | ||
554 | if (sky2->duplex == DUPLEX_FULL) | 586 | if (sky2->duplex == DUPLEX_FULL) |
555 | reg |= GM_GPCR_DUP_FULL; | 587 | reg |= GM_GPCR_DUP_FULL; |
588 | |||
589 | /* turn off pause in 10/100mbps half duplex */ | ||
590 | else if (sky2->speed != SPEED_1000 && | ||
591 | hw->chip_id != CHIP_ID_YUKON_EC_U) | ||
592 | sky2->tx_pause = sky2->rx_pause = 0; | ||
556 | } else | 593 | } else |
557 | reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; | 594 | reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; |
558 | 595 | ||
@@ -719,7 +756,7 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | |||
719 | { | 756 | { |
720 | struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod; | 757 | struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod; |
721 | 758 | ||
722 | sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE; | 759 | sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE); |
723 | return le; | 760 | return le; |
724 | } | 761 | } |
725 | 762 | ||
@@ -735,7 +772,7 @@ static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) | |||
735 | static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) | 772 | static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) |
736 | { | 773 | { |
737 | struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put; | 774 | struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put; |
738 | sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE; | 775 | sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE); |
739 | return le; | 776 | return le; |
740 | } | 777 | } |
741 | 778 | ||
@@ -985,7 +1022,25 @@ static int sky2_up(struct net_device *dev) | |||
985 | struct sky2_hw *hw = sky2->hw; | 1022 | struct sky2_hw *hw = sky2->hw; |
986 | unsigned port = sky2->port; | 1023 | unsigned port = sky2->port; |
987 | u32 ramsize, rxspace, imask; | 1024 | u32 ramsize, rxspace, imask; |
988 | int err = -ENOMEM; | 1025 | int cap, err = -ENOMEM; |
1026 | struct net_device *otherdev = hw->dev[sky2->port^1]; | ||
1027 | |||
1028 | /* | ||
1029 | * On dual port PCI-X card, there is an problem where status | ||
1030 | * can be received out of order due to split transactions | ||
1031 | */ | ||
1032 | if (otherdev && netif_running(otherdev) && | ||
1033 | (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { | ||
1034 | struct sky2_port *osky2 = netdev_priv(otherdev); | ||
1035 | u16 cmd; | ||
1036 | |||
1037 | cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); | ||
1038 | cmd &= ~PCI_X_CMD_MAX_SPLIT; | ||
1039 | sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); | ||
1040 | |||
1041 | sky2->rx_csum = 0; | ||
1042 | osky2->rx_csum = 0; | ||
1043 | } | ||
989 | 1044 | ||
990 | if (netif_msg_ifup(sky2)) | 1045 | if (netif_msg_ifup(sky2)) |
991 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1046 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
@@ -1050,7 +1105,7 @@ static int sky2_up(struct net_device *dev) | |||
1050 | 1105 | ||
1051 | /* Enable interrupts from phy/mac for port */ | 1106 | /* Enable interrupts from phy/mac for port */ |
1052 | imask = sky2_read32(hw, B0_IMSK); | 1107 | imask = sky2_read32(hw, B0_IMSK); |
1053 | imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1108 | imask |= portirq_msk[port]; |
1054 | sky2_write32(hw, B0_IMSK, imask); | 1109 | sky2_write32(hw, B0_IMSK, imask); |
1055 | 1110 | ||
1056 | return 0; | 1111 | return 0; |
@@ -1078,7 +1133,7 @@ err_out: | |||
1078 | /* Modular subtraction in ring */ | 1133 | /* Modular subtraction in ring */ |
1079 | static inline int tx_dist(unsigned tail, unsigned head) | 1134 | static inline int tx_dist(unsigned tail, unsigned head) |
1080 | { | 1135 | { |
1081 | return (head - tail) % TX_RING_SIZE; | 1136 | return (head - tail) & (TX_RING_SIZE - 1); |
1082 | } | 1137 | } |
1083 | 1138 | ||
1084 | /* Number of list elements available for next tx */ | 1139 | /* Number of list elements available for next tx */ |
@@ -1255,7 +1310,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1255 | le->opcode = OP_BUFFER | HW_OWNER; | 1310 | le->opcode = OP_BUFFER | HW_OWNER; |
1256 | 1311 | ||
1257 | fre = sky2->tx_ring | 1312 | fre = sky2->tx_ring |
1258 | + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE; | 1313 | + RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE); |
1259 | pci_unmap_addr_set(fre, mapaddr, mapping); | 1314 | pci_unmap_addr_set(fre, mapaddr, mapping); |
1260 | } | 1315 | } |
1261 | 1316 | ||
@@ -1315,7 +1370,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1315 | 1370 | ||
1316 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 1371 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
1317 | struct tx_ring_info *fre; | 1372 | struct tx_ring_info *fre; |
1318 | fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; | 1373 | fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE); |
1319 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), | 1374 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), |
1320 | skb_shinfo(skb)->frags[i].size, | 1375 | skb_shinfo(skb)->frags[i].size, |
1321 | PCI_DMA_TODEVICE); | 1376 | PCI_DMA_TODEVICE); |
@@ -1401,7 +1456,7 @@ static int sky2_down(struct net_device *dev) | |||
1401 | 1456 | ||
1402 | /* Disable port IRQ */ | 1457 | /* Disable port IRQ */ |
1403 | imask = sky2_read32(hw, B0_IMSK); | 1458 | imask = sky2_read32(hw, B0_IMSK); |
1404 | imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1459 | imask &= ~portirq_msk[port]; |
1405 | sky2_write32(hw, B0_IMSK, imask); | 1460 | sky2_write32(hw, B0_IMSK, imask); |
1406 | 1461 | ||
1407 | /* turn off LED's */ | 1462 | /* turn off LED's */ |
@@ -1498,17 +1553,26 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1498 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1553 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
1499 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1554 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
1500 | 1555 | ||
1501 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | 1556 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) { |
1502 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 1557 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
1558 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ | ||
1559 | |||
1560 | switch(sky2->speed) { | ||
1561 | case SPEED_10: | ||
1562 | led |= PHY_M_LEDC_INIT_CTRL(7); | ||
1563 | break; | ||
1564 | |||
1565 | case SPEED_100: | ||
1566 | led |= PHY_M_LEDC_STA1_CTRL(7); | ||
1567 | break; | ||
1568 | |||
1569 | case SPEED_1000: | ||
1570 | led |= PHY_M_LEDC_STA0_CTRL(7); | ||
1571 | break; | ||
1572 | } | ||
1503 | 1573 | ||
1504 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 1574 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); |
1505 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | 1575 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led); |
1506 | PHY_M_LEDC_INIT_CTRL(sky2->speed == | ||
1507 | SPEED_10 ? 7 : 0) | | ||
1508 | PHY_M_LEDC_STA1_CTRL(sky2->speed == | ||
1509 | SPEED_100 ? 7 : 0) | | ||
1510 | PHY_M_LEDC_STA0_CTRL(sky2->speed == | ||
1511 | SPEED_1000 ? 7 : 0)); | ||
1512 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 1576 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
1513 | } | 1577 | } |
1514 | 1578 | ||
@@ -1583,7 +1647,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1583 | sky2->speed = sky2_phy_speed(hw, aux); | 1647 | sky2->speed = sky2_phy_speed(hw, aux); |
1584 | 1648 | ||
1585 | /* Pause bits are offset (9..8) */ | 1649 | /* Pause bits are offset (9..8) */ |
1586 | if (hw->chip_id == CHIP_ID_YUKON_XL) | 1650 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) |
1587 | aux >>= 6; | 1651 | aux >>= 6; |
1588 | 1652 | ||
1589 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; | 1653 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; |
@@ -1855,39 +1919,38 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1855 | } | 1919 | } |
1856 | } | 1920 | } |
1857 | 1921 | ||
1922 | /* Is status ring empty or is there more to do? */ | ||
1923 | static inline int sky2_more_work(const struct sky2_hw *hw) | ||
1924 | { | ||
1925 | return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); | ||
1926 | } | ||
1927 | |||
1858 | /* Process status response ring */ | 1928 | /* Process status response ring */ |
1859 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1929 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1860 | { | 1930 | { |
1861 | int work_done = 0; | 1931 | int work_done = 0; |
1932 | u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1862 | 1933 | ||
1863 | rmb(); | 1934 | rmb(); |
1864 | 1935 | ||
1865 | for(;;) { | 1936 | while (hw->st_idx != hwidx) { |
1866 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1937 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
1867 | struct net_device *dev; | 1938 | struct net_device *dev; |
1868 | struct sky2_port *sky2; | 1939 | struct sky2_port *sky2; |
1869 | struct sk_buff *skb; | 1940 | struct sk_buff *skb; |
1870 | u32 status; | 1941 | u32 status; |
1871 | u16 length; | 1942 | u16 length; |
1872 | u8 link, opcode; | ||
1873 | 1943 | ||
1874 | opcode = le->opcode; | 1944 | hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); |
1875 | if (!opcode) | ||
1876 | break; | ||
1877 | opcode &= ~HW_OWNER; | ||
1878 | 1945 | ||
1879 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; | 1946 | BUG_ON(le->link >= 2); |
1880 | le->opcode = 0; | 1947 | dev = hw->dev[le->link]; |
1881 | |||
1882 | link = le->link; | ||
1883 | BUG_ON(link >= 2); | ||
1884 | dev = hw->dev[link]; | ||
1885 | 1948 | ||
1886 | sky2 = netdev_priv(dev); | 1949 | sky2 = netdev_priv(dev); |
1887 | length = le->length; | 1950 | length = le->length; |
1888 | status = le->status; | 1951 | status = le->status; |
1889 | 1952 | ||
1890 | switch (opcode) { | 1953 | switch (le->opcode & ~HW_OWNER) { |
1891 | case OP_RXSTAT: | 1954 | case OP_RXSTAT: |
1892 | skb = sky2_receive(sky2, length, status); | 1955 | skb = sky2_receive(sky2, length, status); |
1893 | if (!skb) | 1956 | if (!skb) |
@@ -1927,7 +1990,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
1927 | 1990 | ||
1928 | case OP_TXINDEXLE: | 1991 | case OP_TXINDEXLE: |
1929 | /* TX index reports status for both ports */ | 1992 | /* TX index reports status for both ports */ |
1930 | sky2_tx_done(hw->dev[0], status & 0xffff); | 1993 | BUILD_BUG_ON(TX_RING_SIZE > 0x1000); |
1994 | sky2_tx_done(hw->dev[0], status & 0xfff); | ||
1931 | if (hw->dev[1]) | 1995 | if (hw->dev[1]) |
1932 | sky2_tx_done(hw->dev[1], | 1996 | sky2_tx_done(hw->dev[1], |
1933 | ((status >> 24) & 0xff) | 1997 | ((status >> 24) & 0xff) |
@@ -1937,8 +2001,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
1937 | default: | 2001 | default: |
1938 | if (net_ratelimit()) | 2002 | if (net_ratelimit()) |
1939 | printk(KERN_WARNING PFX | 2003 | printk(KERN_WARNING PFX |
1940 | "unknown status opcode 0x%x\n", opcode); | 2004 | "unknown status opcode 0x%x\n", le->opcode); |
1941 | break; | 2005 | goto exit_loop; |
1942 | } | 2006 | } |
1943 | } | 2007 | } |
1944 | 2008 | ||
@@ -2089,12 +2153,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2089 | */ | 2153 | */ |
2090 | static void sky2_idle(unsigned long arg) | 2154 | static void sky2_idle(unsigned long arg) |
2091 | { | 2155 | { |
2092 | struct net_device *dev = (struct net_device *) arg; | 2156 | struct sky2_hw *hw = (struct sky2_hw *) arg; |
2157 | struct net_device *dev = hw->dev[0]; | ||
2093 | 2158 | ||
2094 | local_irq_disable(); | ||
2095 | if (__netif_rx_schedule_prep(dev)) | 2159 | if (__netif_rx_schedule_prep(dev)) |
2096 | __netif_rx_schedule(dev); | 2160 | __netif_rx_schedule(dev); |
2097 | local_irq_enable(); | 2161 | |
2162 | mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); | ||
2098 | } | 2163 | } |
2099 | 2164 | ||
2100 | 2165 | ||
@@ -2105,65 +2170,46 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2105 | int work_done = 0; | 2170 | int work_done = 0; |
2106 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2171 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2107 | 2172 | ||
2108 | restart_poll: | 2173 | if (status & Y2_IS_HW_ERR) |
2109 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2174 | sky2_hw_intr(hw); |
2110 | if (status & Y2_IS_HW_ERR) | ||
2111 | sky2_hw_intr(hw); | ||
2112 | 2175 | ||
2113 | if (status & Y2_IS_IRQ_PHY1) | 2176 | if (status & Y2_IS_IRQ_PHY1) |
2114 | sky2_phy_intr(hw, 0); | 2177 | sky2_phy_intr(hw, 0); |
2115 | 2178 | ||
2116 | if (status & Y2_IS_IRQ_PHY2) | 2179 | if (status & Y2_IS_IRQ_PHY2) |
2117 | sky2_phy_intr(hw, 1); | 2180 | sky2_phy_intr(hw, 1); |
2118 | 2181 | ||
2119 | if (status & Y2_IS_IRQ_MAC1) | 2182 | if (status & Y2_IS_IRQ_MAC1) |
2120 | sky2_mac_intr(hw, 0); | 2183 | sky2_mac_intr(hw, 0); |
2121 | 2184 | ||
2122 | if (status & Y2_IS_IRQ_MAC2) | 2185 | if (status & Y2_IS_IRQ_MAC2) |
2123 | sky2_mac_intr(hw, 1); | 2186 | sky2_mac_intr(hw, 1); |
2124 | 2187 | ||
2125 | if (status & Y2_IS_CHK_RX1) | 2188 | if (status & Y2_IS_CHK_RX1) |
2126 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); | 2189 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); |
2127 | 2190 | ||
2128 | if (status & Y2_IS_CHK_RX2) | 2191 | if (status & Y2_IS_CHK_RX2) |
2129 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); | 2192 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); |
2130 | 2193 | ||
2131 | if (status & Y2_IS_CHK_TXA1) | 2194 | if (status & Y2_IS_CHK_TXA1) |
2132 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); | 2195 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); |
2133 | 2196 | ||
2134 | if (status & Y2_IS_CHK_TXA2) | 2197 | if (status & Y2_IS_CHK_TXA2) |
2135 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2198 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
2136 | } | ||
2137 | |||
2138 | if (status & Y2_IS_STAT_BMU) { | ||
2139 | work_done += sky2_status_intr(hw, work_limit - work_done); | ||
2140 | *budget -= work_done; | ||
2141 | dev0->quota -= work_done; | ||
2142 | 2199 | ||
2143 | if (work_done >= work_limit) | 2200 | work_done = sky2_status_intr(hw, work_limit); |
2144 | return 1; | 2201 | *budget -= work_done; |
2202 | dev0->quota -= work_done; | ||
2145 | 2203 | ||
2204 | if (status & Y2_IS_STAT_BMU) | ||
2146 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2205 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2147 | } | ||
2148 | |||
2149 | mod_timer(&hw->idle_timer, jiffies + HZ); | ||
2150 | 2206 | ||
2151 | local_irq_disable(); | 2207 | if (sky2_more_work(hw)) |
2152 | __netif_rx_complete(dev0); | 2208 | return 1; |
2153 | 2209 | ||
2154 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2210 | netif_rx_complete(dev0); |
2155 | |||
2156 | if (unlikely(status)) { | ||
2157 | /* More work pending, try and keep going */ | ||
2158 | if (__netif_rx_schedule_prep(dev0)) { | ||
2159 | __netif_rx_reschedule(dev0, work_done); | ||
2160 | status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2161 | local_irq_enable(); | ||
2162 | goto restart_poll; | ||
2163 | } | ||
2164 | } | ||
2165 | 2211 | ||
2166 | local_irq_enable(); | 2212 | sky2_read32(hw, B0_Y2_SP_LISR); |
2167 | return 0; | 2213 | return 0; |
2168 | } | 2214 | } |
2169 | 2215 | ||
@@ -2244,13 +2290,6 @@ static int __devinit sky2_reset(struct sky2_hw *hw) | |||
2244 | return -EOPNOTSUPP; | 2290 | return -EOPNOTSUPP; |
2245 | } | 2291 | } |
2246 | 2292 | ||
2247 | /* This chip is new and not tested yet */ | ||
2248 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | ||
2249 | pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n", | ||
2250 | pci_name(hw->pdev)); | ||
2251 | pr_info("Please report success/failure to maintainer <shemminger@osdl.org>\n"); | ||
2252 | } | ||
2253 | |||
2254 | /* disable ASF */ | 2293 | /* disable ASF */ |
2255 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2294 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2256 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2295 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
@@ -3054,12 +3093,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3054 | sky2->duplex = -1; | 3093 | sky2->duplex = -1; |
3055 | sky2->speed = -1; | 3094 | sky2->speed = -1; |
3056 | sky2->advertising = sky2_supported_modes(hw); | 3095 | sky2->advertising = sky2_supported_modes(hw); |
3057 | 3096 | sky2->rx_csum = 1; | |
3058 | /* Receive checksum disabled for Yukon XL | ||
3059 | * because of observed problems with incorrect | ||
3060 | * values when multiple packets are received in one interrupt | ||
3061 | */ | ||
3062 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | ||
3063 | 3097 | ||
3064 | spin_lock_init(&sky2->phy_lock); | 3098 | spin_lock_init(&sky2->phy_lock); |
3065 | sky2->tx_pending = TX_DEF_PENDING; | 3099 | sky2->tx_pending = TX_DEF_PENDING; |
@@ -3302,7 +3336,10 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3302 | 3336 | ||
3303 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3337 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3304 | 3338 | ||
3305 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | 3339 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); |
3340 | if (idle_timeout > 0) | ||
3341 | mod_timer(&hw->idle_timer, | ||
3342 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
3306 | 3343 | ||
3307 | pci_set_drvdata(pdev, hw); | 3344 | pci_set_drvdata(pdev, hw); |
3308 | 3345 | ||
@@ -3342,6 +3379,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3342 | del_timer_sync(&hw->idle_timer); | 3379 | del_timer_sync(&hw->idle_timer); |
3343 | 3380 | ||
3344 | sky2_write32(hw, B0_IMSK, 0); | 3381 | sky2_write32(hw, B0_IMSK, 0); |
3382 | synchronize_irq(hw->pdev->irq); | ||
3383 | |||
3345 | dev0 = hw->dev[0]; | 3384 | dev0 = hw->dev[0]; |
3346 | dev1 = hw->dev[1]; | 3385 | dev1 = hw->dev[1]; |
3347 | if (dev1) | 3386 | if (dev1) |