diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 226 |
1 files changed, 137 insertions, 89 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67b0eab16589..ffd267fab21d 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.1" | 54 | #define DRV_VERSION "1.3" |
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,6 +98,10 @@ 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) }, |
@@ -122,6 +128,7 @@ MODULE_DEVICE_TABLE(pci, sky2_id_table); | |||
122 | /* Avoid conditionals by using array */ | 128 | /* Avoid conditionals by using array */ |
123 | static const unsigned txqaddr[] = { Q_XA1, Q_XA2 }; | 129 | static const unsigned txqaddr[] = { Q_XA1, Q_XA2 }; |
124 | static const unsigned rxqaddr[] = { Q_R1, Q_R2 }; | 130 | static const unsigned rxqaddr[] = { Q_R1, Q_R2 }; |
131 | static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 }; | ||
125 | 132 | ||
126 | /* This driver supports yukon2 chipset only */ | 133 | /* This driver supports yukon2 chipset only */ |
127 | static const char *yukon2_name[] = { | 134 | static const char *yukon2_name[] = { |
@@ -298,7 +305,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
298 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | 305 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); |
299 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; | 306 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; |
300 | 307 | ||
301 | if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) { | 308 | if (sky2->autoneg == AUTONEG_ENABLE && |
309 | (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); | 310 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
303 | 311 | ||
304 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | 312 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | |
@@ -326,7 +334,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
326 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); | 334 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); |
327 | 335 | ||
328 | if (sky2->autoneg == AUTONEG_ENABLE && | 336 | if (sky2->autoneg == AUTONEG_ENABLE && |
329 | hw->chip_id == CHIP_ID_YUKON_XL) { | 337 | (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { |
330 | ctrl &= ~PHY_M_PC_DSC_MSK; | 338 | ctrl &= ~PHY_M_PC_DSC_MSK; |
331 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | 339 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; |
332 | } | 340 | } |
@@ -442,10 +450,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
442 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 450 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); |
443 | 451 | ||
444 | /* set LED Function Control register */ | 452 | /* set LED Function Control register */ |
445 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | 453 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, |
446 | PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */ | 454 | (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ |
447 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ | 455 | PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */ |
448 | PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */ | 456 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ |
457 | PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */ | ||
449 | 458 | ||
450 | /* set Polarity Control register */ | 459 | /* set Polarity Control register */ |
451 | gm_phy_write(hw, port, PHY_MARV_PHY_STAT, | 460 | gm_phy_write(hw, port, PHY_MARV_PHY_STAT, |
@@ -459,6 +468,25 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
459 | /* restore page register */ | 468 | /* restore page register */ |
460 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 469 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
461 | break; | 470 | break; |
471 | case CHIP_ID_YUKON_EC_U: | ||
472 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
473 | |||
474 | /* select page 3 to access LED control register */ | ||
475 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
476 | |||
477 | /* set LED Function Control register */ | ||
478 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, | ||
479 | (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | ||
480 | PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */ | ||
481 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ | ||
482 | PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */ | ||
483 | |||
484 | /* set Blink Rate in LED Timer Control Register */ | ||
485 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, | ||
486 | ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS)); | ||
487 | /* restore page register */ | ||
488 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
489 | break; | ||
462 | 490 | ||
463 | default: | 491 | default: |
464 | /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ | 492 | /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ |
@@ -467,19 +495,21 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
467 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); | 495 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); |
468 | } | 496 | } |
469 | 497 | ||
470 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) { | 498 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) { |
471 | /* apply fixes in PHY AFE */ | 499 | /* apply fixes in PHY AFE */ |
472 | gm_phy_write(hw, port, 22, 255); | 500 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
501 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255); | ||
502 | |||
473 | /* increase differential signal amplitude in 10BASE-T */ | 503 | /* increase differential signal amplitude in 10BASE-T */ |
474 | gm_phy_write(hw, port, 24, 0xaa99); | 504 | gm_phy_write(hw, port, 0x18, 0xaa99); |
475 | gm_phy_write(hw, port, 23, 0x2011); | 505 | gm_phy_write(hw, port, 0x17, 0x2011); |
476 | 506 | ||
477 | /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ | 507 | /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ |
478 | gm_phy_write(hw, port, 24, 0xa204); | 508 | gm_phy_write(hw, port, 0x18, 0xa204); |
479 | gm_phy_write(hw, port, 23, 0x2002); | 509 | gm_phy_write(hw, port, 0x17, 0x2002); |
480 | 510 | ||
481 | /* set page register to 0 */ | 511 | /* set page register to 0 */ |
482 | gm_phy_write(hw, port, 22, 0); | 512 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
483 | } else { | 513 | } else { |
484 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 514 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); |
485 | 515 | ||
@@ -553,6 +583,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
553 | 583 | ||
554 | if (sky2->duplex == DUPLEX_FULL) | 584 | if (sky2->duplex == DUPLEX_FULL) |
555 | reg |= GM_GPCR_DUP_FULL; | 585 | reg |= GM_GPCR_DUP_FULL; |
586 | |||
587 | /* turn off pause in 10/100mbps half duplex */ | ||
588 | else if (sky2->speed != SPEED_1000 && | ||
589 | hw->chip_id != CHIP_ID_YUKON_EC_U) | ||
590 | sky2->tx_pause = sky2->rx_pause = 0; | ||
556 | } else | 591 | } else |
557 | reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; | 592 | reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; |
558 | 593 | ||
@@ -719,7 +754,7 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | |||
719 | { | 754 | { |
720 | struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod; | 755 | struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod; |
721 | 756 | ||
722 | sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE; | 757 | sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE); |
723 | return le; | 758 | return le; |
724 | } | 759 | } |
725 | 760 | ||
@@ -735,7 +770,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) | 770 | static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) |
736 | { | 771 | { |
737 | struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put; | 772 | struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put; |
738 | sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE; | 773 | sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE); |
739 | return le; | 774 | return le; |
740 | } | 775 | } |
741 | 776 | ||
@@ -925,8 +960,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | |||
925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | 960 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
926 | if (likely(skb)) { | 961 | if (likely(skb)) { |
927 | unsigned long p = (unsigned long) skb->data; | 962 | unsigned long p = (unsigned long) skb->data; |
928 | skb_reserve(skb, | 963 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
929 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
930 | } | 964 | } |
931 | 965 | ||
932 | return skb; | 966 | return skb; |
@@ -1051,7 +1085,7 @@ static int sky2_up(struct net_device *dev) | |||
1051 | 1085 | ||
1052 | /* Enable interrupts from phy/mac for port */ | 1086 | /* Enable interrupts from phy/mac for port */ |
1053 | imask = sky2_read32(hw, B0_IMSK); | 1087 | imask = sky2_read32(hw, B0_IMSK); |
1054 | imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1088 | imask |= portirq_msk[port]; |
1055 | sky2_write32(hw, B0_IMSK, imask); | 1089 | sky2_write32(hw, B0_IMSK, imask); |
1056 | 1090 | ||
1057 | return 0; | 1091 | return 0; |
@@ -1079,7 +1113,7 @@ err_out: | |||
1079 | /* Modular subtraction in ring */ | 1113 | /* Modular subtraction in ring */ |
1080 | static inline int tx_dist(unsigned tail, unsigned head) | 1114 | static inline int tx_dist(unsigned tail, unsigned head) |
1081 | { | 1115 | { |
1082 | return (head - tail) % TX_RING_SIZE; | 1116 | return (head - tail) & (TX_RING_SIZE - 1); |
1083 | } | 1117 | } |
1084 | 1118 | ||
1085 | /* Number of list elements available for next tx */ | 1119 | /* Number of list elements available for next tx */ |
@@ -1256,7 +1290,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1256 | le->opcode = OP_BUFFER | HW_OWNER; | 1290 | le->opcode = OP_BUFFER | HW_OWNER; |
1257 | 1291 | ||
1258 | fre = sky2->tx_ring | 1292 | fre = sky2->tx_ring |
1259 | + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE; | 1293 | + RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE); |
1260 | pci_unmap_addr_set(fre, mapaddr, mapping); | 1294 | pci_unmap_addr_set(fre, mapaddr, mapping); |
1261 | } | 1295 | } |
1262 | 1296 | ||
@@ -1316,7 +1350,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1316 | 1350 | ||
1317 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 1351 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
1318 | struct tx_ring_info *fre; | 1352 | struct tx_ring_info *fre; |
1319 | fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; | 1353 | fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE); |
1320 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), | 1354 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), |
1321 | skb_shinfo(skb)->frags[i].size, | 1355 | skb_shinfo(skb)->frags[i].size, |
1322 | PCI_DMA_TODEVICE); | 1356 | PCI_DMA_TODEVICE); |
@@ -1402,7 +1436,7 @@ static int sky2_down(struct net_device *dev) | |||
1402 | 1436 | ||
1403 | /* Disable port IRQ */ | 1437 | /* Disable port IRQ */ |
1404 | imask = sky2_read32(hw, B0_IMSK); | 1438 | imask = sky2_read32(hw, B0_IMSK); |
1405 | imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1439 | imask &= ~portirq_msk[port]; |
1406 | sky2_write32(hw, B0_IMSK, imask); | 1440 | sky2_write32(hw, B0_IMSK, imask); |
1407 | 1441 | ||
1408 | /* turn off LED's */ | 1442 | /* turn off LED's */ |
@@ -1499,17 +1533,26 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1499 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1533 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
1500 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1534 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
1501 | 1535 | ||
1502 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | 1536 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) { |
1503 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 1537 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
1538 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ | ||
1539 | |||
1540 | switch(sky2->speed) { | ||
1541 | case SPEED_10: | ||
1542 | led |= PHY_M_LEDC_INIT_CTRL(7); | ||
1543 | break; | ||
1544 | |||
1545 | case SPEED_100: | ||
1546 | led |= PHY_M_LEDC_STA1_CTRL(7); | ||
1547 | break; | ||
1548 | |||
1549 | case SPEED_1000: | ||
1550 | led |= PHY_M_LEDC_STA0_CTRL(7); | ||
1551 | break; | ||
1552 | } | ||
1504 | 1553 | ||
1505 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 1554 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); |
1506 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | 1555 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led); |
1507 | PHY_M_LEDC_INIT_CTRL(sky2->speed == | ||
1508 | SPEED_10 ? 7 : 0) | | ||
1509 | PHY_M_LEDC_STA1_CTRL(sky2->speed == | ||
1510 | SPEED_100 ? 7 : 0) | | ||
1511 | PHY_M_LEDC_STA0_CTRL(sky2->speed == | ||
1512 | SPEED_1000 ? 7 : 0)); | ||
1513 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | 1556 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
1514 | } | 1557 | } |
1515 | 1558 | ||
@@ -1584,7 +1627,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1584 | sky2->speed = sky2_phy_speed(hw, aux); | 1627 | sky2->speed = sky2_phy_speed(hw, aux); |
1585 | 1628 | ||
1586 | /* Pause bits are offset (9..8) */ | 1629 | /* Pause bits are offset (9..8) */ |
1587 | if (hw->chip_id == CHIP_ID_YUKON_XL) | 1630 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) |
1588 | aux >>= 6; | 1631 | aux >>= 6; |
1589 | 1632 | ||
1590 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; | 1633 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; |
@@ -1686,13 +1729,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1686 | } | 1729 | } |
1687 | 1730 | ||
1688 | 1731 | ||
1689 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
1690 | /* Want receive buffer size to be multiple of 64 bits | 1732 | /* Want receive buffer size to be multiple of 64 bits |
1691 | * and incl room for vlan and truncation | 1733 | * and incl room for vlan and truncation |
1692 | */ | 1734 | */ |
1693 | static inline unsigned sky2_buf_size(int mtu) | 1735 | static inline unsigned sky2_buf_size(int mtu) |
1694 | { | 1736 | { |
1695 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1737 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
1696 | } | 1738 | } |
1697 | 1739 | ||
1698 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1740 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -1861,35 +1903,28 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1861 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1903 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1862 | { | 1904 | { |
1863 | int work_done = 0; | 1905 | int work_done = 0; |
1906 | u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1864 | 1907 | ||
1865 | rmb(); | 1908 | rmb(); |
1866 | 1909 | ||
1867 | for(;;) { | 1910 | while (hw->st_idx != hwidx) { |
1868 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1911 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
1869 | struct net_device *dev; | 1912 | struct net_device *dev; |
1870 | struct sky2_port *sky2; | 1913 | struct sky2_port *sky2; |
1871 | struct sk_buff *skb; | 1914 | struct sk_buff *skb; |
1872 | u32 status; | 1915 | u32 status; |
1873 | u16 length; | 1916 | u16 length; |
1874 | u8 link, opcode; | ||
1875 | 1917 | ||
1876 | opcode = le->opcode; | 1918 | hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); |
1877 | if (!opcode) | ||
1878 | break; | ||
1879 | opcode &= ~HW_OWNER; | ||
1880 | 1919 | ||
1881 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; | 1920 | BUG_ON(le->link >= 2); |
1882 | le->opcode = 0; | 1921 | dev = hw->dev[le->link]; |
1883 | |||
1884 | link = le->link; | ||
1885 | BUG_ON(link >= 2); | ||
1886 | dev = hw->dev[link]; | ||
1887 | 1922 | ||
1888 | sky2 = netdev_priv(dev); | 1923 | sky2 = netdev_priv(dev); |
1889 | length = le->length; | 1924 | length = le->length; |
1890 | status = le->status; | 1925 | status = le->status; |
1891 | 1926 | ||
1892 | switch (opcode) { | 1927 | switch (le->opcode & ~HW_OWNER) { |
1893 | case OP_RXSTAT: | 1928 | case OP_RXSTAT: |
1894 | skb = sky2_receive(sky2, length, status); | 1929 | skb = sky2_receive(sky2, length, status); |
1895 | if (!skb) | 1930 | if (!skb) |
@@ -1929,7 +1964,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
1929 | 1964 | ||
1930 | case OP_TXINDEXLE: | 1965 | case OP_TXINDEXLE: |
1931 | /* TX index reports status for both ports */ | 1966 | /* TX index reports status for both ports */ |
1932 | sky2_tx_done(hw->dev[0], status & 0xffff); | 1967 | BUILD_BUG_ON(TX_RING_SIZE > 0x1000); |
1968 | sky2_tx_done(hw->dev[0], status & 0xfff); | ||
1933 | if (hw->dev[1]) | 1969 | if (hw->dev[1]) |
1934 | sky2_tx_done(hw->dev[1], | 1970 | sky2_tx_done(hw->dev[1], |
1935 | ((status >> 24) & 0xff) | 1971 | ((status >> 24) & 0xff) |
@@ -1939,8 +1975,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
1939 | default: | 1975 | default: |
1940 | if (net_ratelimit()) | 1976 | if (net_ratelimit()) |
1941 | printk(KERN_WARNING PFX | 1977 | printk(KERN_WARNING PFX |
1942 | "unknown status opcode 0x%x\n", opcode); | 1978 | "unknown status opcode 0x%x\n", le->opcode); |
1943 | break; | 1979 | goto exit_loop; |
1944 | } | 1980 | } |
1945 | } | 1981 | } |
1946 | 1982 | ||
@@ -2086,6 +2122,21 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2086 | } | 2122 | } |
2087 | } | 2123 | } |
2088 | 2124 | ||
2125 | /* If idle then force a fake soft NAPI poll once a second | ||
2126 | * to work around cases where sharing an edge triggered interrupt. | ||
2127 | */ | ||
2128 | static void sky2_idle(unsigned long arg) | ||
2129 | { | ||
2130 | struct sky2_hw *hw = (struct sky2_hw *) arg; | ||
2131 | struct net_device *dev = hw->dev[0]; | ||
2132 | |||
2133 | if (__netif_rx_schedule_prep(dev)) | ||
2134 | __netif_rx_schedule(dev); | ||
2135 | |||
2136 | mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); | ||
2137 | } | ||
2138 | |||
2139 | |||
2089 | static int sky2_poll(struct net_device *dev0, int *budget) | 2140 | static int sky2_poll(struct net_device *dev0, int *budget) |
2090 | { | 2141 | { |
2091 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2142 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
@@ -2093,45 +2144,42 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2093 | int work_done = 0; | 2144 | int work_done = 0; |
2094 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2145 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2095 | 2146 | ||
2096 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2147 | if (status & Y2_IS_HW_ERR) |
2097 | if (status & Y2_IS_HW_ERR) | 2148 | sky2_hw_intr(hw); |
2098 | sky2_hw_intr(hw); | ||
2099 | 2149 | ||
2100 | if (status & Y2_IS_IRQ_PHY1) | 2150 | if (status & Y2_IS_IRQ_PHY1) |
2101 | sky2_phy_intr(hw, 0); | 2151 | sky2_phy_intr(hw, 0); |
2102 | 2152 | ||
2103 | if (status & Y2_IS_IRQ_PHY2) | 2153 | if (status & Y2_IS_IRQ_PHY2) |
2104 | sky2_phy_intr(hw, 1); | 2154 | sky2_phy_intr(hw, 1); |
2105 | 2155 | ||
2106 | if (status & Y2_IS_IRQ_MAC1) | 2156 | if (status & Y2_IS_IRQ_MAC1) |
2107 | sky2_mac_intr(hw, 0); | 2157 | sky2_mac_intr(hw, 0); |
2108 | 2158 | ||
2109 | if (status & Y2_IS_IRQ_MAC2) | 2159 | if (status & Y2_IS_IRQ_MAC2) |
2110 | sky2_mac_intr(hw, 1); | 2160 | sky2_mac_intr(hw, 1); |
2111 | 2161 | ||
2112 | if (status & Y2_IS_CHK_RX1) | 2162 | if (status & Y2_IS_CHK_RX1) |
2113 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); | 2163 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); |
2114 | 2164 | ||
2115 | if (status & Y2_IS_CHK_RX2) | 2165 | if (status & Y2_IS_CHK_RX2) |
2116 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); | 2166 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); |
2117 | 2167 | ||
2118 | if (status & Y2_IS_CHK_TXA1) | 2168 | if (status & Y2_IS_CHK_TXA1) |
2119 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); | 2169 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); |
2120 | 2170 | ||
2121 | if (status & Y2_IS_CHK_TXA2) | 2171 | if (status & Y2_IS_CHK_TXA2) |
2122 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2172 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
2123 | } | ||
2124 | 2173 | ||
2125 | if (status & Y2_IS_STAT_BMU) { | 2174 | if (status & Y2_IS_STAT_BMU) |
2126 | work_done = sky2_status_intr(hw, work_limit); | 2175 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2127 | *budget -= work_done; | ||
2128 | dev0->quota -= work_done; | ||
2129 | 2176 | ||
2130 | if (work_done >= work_limit) | 2177 | work_done = sky2_status_intr(hw, work_limit); |
2131 | return 1; | 2178 | *budget -= work_done; |
2179 | dev0->quota -= work_done; | ||
2132 | 2180 | ||
2133 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2181 | if (work_done >= work_limit) |
2134 | } | 2182 | return 1; |
2135 | 2183 | ||
2136 | netif_rx_complete(dev0); | 2184 | netif_rx_complete(dev0); |
2137 | 2185 | ||
@@ -2153,8 +2201,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2153 | prefetch(&hw->st_le[hw->st_idx]); | 2201 | prefetch(&hw->st_le[hw->st_idx]); |
2154 | if (likely(__netif_rx_schedule_prep(dev0))) | 2202 | if (likely(__netif_rx_schedule_prep(dev0))) |
2155 | __netif_rx_schedule(dev0); | 2203 | __netif_rx_schedule(dev0); |
2156 | else | ||
2157 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
2158 | 2204 | ||
2159 | return IRQ_HANDLED; | 2205 | return IRQ_HANDLED; |
2160 | } | 2206 | } |
@@ -2193,7 +2239,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2193 | } | 2239 | } |
2194 | 2240 | ||
2195 | 2241 | ||
2196 | static int sky2_reset(struct sky2_hw *hw) | 2242 | static int __devinit sky2_reset(struct sky2_hw *hw) |
2197 | { | 2243 | { |
2198 | u16 status; | 2244 | u16 status; |
2199 | u8 t8, pmd_type; | 2245 | u8 t8, pmd_type; |
@@ -2218,13 +2264,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2218 | return -EOPNOTSUPP; | 2264 | return -EOPNOTSUPP; |
2219 | } | 2265 | } |
2220 | 2266 | ||
2221 | /* This chip is new and not tested yet */ | ||
2222 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | ||
2223 | pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n", | ||
2224 | pci_name(hw->pdev)); | ||
2225 | pr_info("Please report success/failure to maintainer <shemminger@osdl.org>\n"); | ||
2226 | } | ||
2227 | |||
2228 | /* disable ASF */ | 2267 | /* disable ASF */ |
2229 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2268 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2230 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2269 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
@@ -3276,6 +3315,11 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3276 | 3315 | ||
3277 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3316 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3278 | 3317 | ||
3318 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | ||
3319 | if (idle_timeout > 0) | ||
3320 | mod_timer(&hw->idle_timer, | ||
3321 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
3322 | |||
3279 | pci_set_drvdata(pdev, hw); | 3323 | pci_set_drvdata(pdev, hw); |
3280 | 3324 | ||
3281 | return 0; | 3325 | return 0; |
@@ -3311,13 +3355,17 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3311 | if (!hw) | 3355 | if (!hw) |
3312 | return; | 3356 | return; |
3313 | 3357 | ||
3358 | del_timer_sync(&hw->idle_timer); | ||
3359 | |||
3360 | sky2_write32(hw, B0_IMSK, 0); | ||
3361 | synchronize_irq(hw->pdev->irq); | ||
3362 | |||
3314 | dev0 = hw->dev[0]; | 3363 | dev0 = hw->dev[0]; |
3315 | dev1 = hw->dev[1]; | 3364 | dev1 = hw->dev[1]; |
3316 | if (dev1) | 3365 | if (dev1) |
3317 | unregister_netdev(dev1); | 3366 | unregister_netdev(dev1); |
3318 | unregister_netdev(dev0); | 3367 | unregister_netdev(dev0); |
3319 | 3368 | ||
3320 | sky2_write32(hw, B0_IMSK, 0); | ||
3321 | sky2_set_power_state(hw, PCI_D3hot); | 3369 | sky2_set_power_state(hw, PCI_D3hot); |
3322 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3370 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
3323 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3371 | sky2_write8(hw, B0_CTST, CS_RST_SET); |