diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 282 |
1 files changed, 182 insertions, 100 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67b0eab16589..959109609d85 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.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 | ||
@@ -925,8 +962,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); | 962 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
926 | if (likely(skb)) { | 963 | if (likely(skb)) { |
927 | unsigned long p = (unsigned long) skb->data; | 964 | unsigned long p = (unsigned long) skb->data; |
928 | skb_reserve(skb, | 965 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
929 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
930 | } | 966 | } |
931 | 967 | ||
932 | return skb; | 968 | return skb; |
@@ -943,6 +979,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
943 | struct sky2_hw *hw = sky2->hw; | 979 | struct sky2_hw *hw = sky2->hw; |
944 | unsigned rxq = rxqaddr[sky2->port]; | 980 | unsigned rxq = rxqaddr[sky2->port]; |
945 | int i; | 981 | int i; |
982 | unsigned thresh; | ||
946 | 983 | ||
947 | sky2->rx_put = sky2->rx_next = 0; | 984 | sky2->rx_put = sky2->rx_next = 0; |
948 | sky2_qset(hw, rxq); | 985 | sky2_qset(hw, rxq); |
@@ -967,9 +1004,21 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
967 | sky2_rx_add(sky2, re->mapaddr); | 1004 | sky2_rx_add(sky2, re->mapaddr); |
968 | } | 1005 | } |
969 | 1006 | ||
970 | /* Truncate oversize frames */ | 1007 | |
971 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8); | 1008 | /* |
972 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | 1009 | * The receiver hangs if it receives frames larger than the |
1010 | * packet buffer. As a workaround, truncate oversize frames, but | ||
1011 | * the register is limited to 9 bits, so if you do frames > 2052 | ||
1012 | * you better get the MTU right! | ||
1013 | */ | ||
1014 | thresh = (sky2->rx_bufsize - 8) / sizeof(u32); | ||
1015 | if (thresh > 0x1ff) | ||
1016 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); | ||
1017 | else { | ||
1018 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh); | ||
1019 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | ||
1020 | } | ||
1021 | |||
973 | 1022 | ||
974 | /* Tell chip about available buffers */ | 1023 | /* Tell chip about available buffers */ |
975 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 1024 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); |
@@ -986,7 +1035,25 @@ static int sky2_up(struct net_device *dev) | |||
986 | struct sky2_hw *hw = sky2->hw; | 1035 | struct sky2_hw *hw = sky2->hw; |
987 | unsigned port = sky2->port; | 1036 | unsigned port = sky2->port; |
988 | u32 ramsize, rxspace, imask; | 1037 | u32 ramsize, rxspace, imask; |
989 | int err = -ENOMEM; | 1038 | int cap, err = -ENOMEM; |
1039 | struct net_device *otherdev = hw->dev[sky2->port^1]; | ||
1040 | |||
1041 | /* | ||
1042 | * On dual port PCI-X card, there is an problem where status | ||
1043 | * can be received out of order due to split transactions | ||
1044 | */ | ||
1045 | if (otherdev && netif_running(otherdev) && | ||
1046 | (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { | ||
1047 | struct sky2_port *osky2 = netdev_priv(otherdev); | ||
1048 | u16 cmd; | ||
1049 | |||
1050 | cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); | ||
1051 | cmd &= ~PCI_X_CMD_MAX_SPLIT; | ||
1052 | sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); | ||
1053 | |||
1054 | sky2->rx_csum = 0; | ||
1055 | osky2->rx_csum = 0; | ||
1056 | } | ||
990 | 1057 | ||
991 | if (netif_msg_ifup(sky2)) | 1058 | if (netif_msg_ifup(sky2)) |
992 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1059 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
@@ -1051,7 +1118,7 @@ static int sky2_up(struct net_device *dev) | |||
1051 | 1118 | ||
1052 | /* Enable interrupts from phy/mac for port */ | 1119 | /* Enable interrupts from phy/mac for port */ |
1053 | imask = sky2_read32(hw, B0_IMSK); | 1120 | imask = sky2_read32(hw, B0_IMSK); |
1054 | imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1121 | imask |= portirq_msk[port]; |
1055 | sky2_write32(hw, B0_IMSK, imask); | 1122 | sky2_write32(hw, B0_IMSK, imask); |
1056 | 1123 | ||
1057 | return 0; | 1124 | return 0; |
@@ -1079,7 +1146,7 @@ err_out: | |||
1079 | /* Modular subtraction in ring */ | 1146 | /* Modular subtraction in ring */ |
1080 | static inline int tx_dist(unsigned tail, unsigned head) | 1147 | static inline int tx_dist(unsigned tail, unsigned head) |
1081 | { | 1148 | { |
1082 | return (head - tail) % TX_RING_SIZE; | 1149 | return (head - tail) & (TX_RING_SIZE - 1); |
1083 | } | 1150 | } |
1084 | 1151 | ||
1085 | /* Number of list elements available for next tx */ | 1152 | /* Number of list elements available for next tx */ |
@@ -1256,7 +1323,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1256 | le->opcode = OP_BUFFER | HW_OWNER; | 1323 | le->opcode = OP_BUFFER | HW_OWNER; |
1257 | 1324 | ||
1258 | fre = sky2->tx_ring | 1325 | fre = sky2->tx_ring |
1259 | + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE; | 1326 | + RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE); |
1260 | pci_unmap_addr_set(fre, mapaddr, mapping); | 1327 | pci_unmap_addr_set(fre, mapaddr, mapping); |
1261 | } | 1328 | } |
1262 | 1329 | ||
@@ -1316,7 +1383,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1316 | 1383 | ||
1317 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 1384 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
1318 | struct tx_ring_info *fre; | 1385 | struct tx_ring_info *fre; |
1319 | fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; | 1386 | fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE); |
1320 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), | 1387 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), |
1321 | skb_shinfo(skb)->frags[i].size, | 1388 | skb_shinfo(skb)->frags[i].size, |
1322 | PCI_DMA_TODEVICE); | 1389 | PCI_DMA_TODEVICE); |
@@ -1402,7 +1469,7 @@ static int sky2_down(struct net_device *dev) | |||
1402 | 1469 | ||
1403 | /* Disable port IRQ */ | 1470 | /* Disable port IRQ */ |
1404 | imask = sky2_read32(hw, B0_IMSK); | 1471 | imask = sky2_read32(hw, B0_IMSK); |
1405 | imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1472 | imask &= ~portirq_msk[port]; |
1406 | sky2_write32(hw, B0_IMSK, imask); | 1473 | sky2_write32(hw, B0_IMSK, imask); |
1407 | 1474 | ||
1408 | /* turn off LED's */ | 1475 | /* turn off LED's */ |
@@ -1499,17 +1566,26 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1499 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1566 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
1500 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1567 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
1501 | 1568 | ||
1502 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | 1569 | 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); | 1570 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
1571 | u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ | ||
1572 | |||
1573 | switch(sky2->speed) { | ||
1574 | case SPEED_10: | ||
1575 | led |= PHY_M_LEDC_INIT_CTRL(7); | ||
1576 | break; | ||
1577 | |||
1578 | case SPEED_100: | ||
1579 | led |= PHY_M_LEDC_STA1_CTRL(7); | ||
1580 | break; | ||
1581 | |||
1582 | case SPEED_1000: | ||
1583 | led |= PHY_M_LEDC_STA0_CTRL(7); | ||
1584 | break; | ||
1585 | } | ||
1504 | 1586 | ||
1505 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 1587 | 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 */ | 1588 | 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); | 1589 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); |
1514 | } | 1590 | } |
1515 | 1591 | ||
@@ -1584,7 +1660,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1584 | sky2->speed = sky2_phy_speed(hw, aux); | 1660 | sky2->speed = sky2_phy_speed(hw, aux); |
1585 | 1661 | ||
1586 | /* Pause bits are offset (9..8) */ | 1662 | /* Pause bits are offset (9..8) */ |
1587 | if (hw->chip_id == CHIP_ID_YUKON_XL) | 1663 | if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) |
1588 | aux >>= 6; | 1664 | aux >>= 6; |
1589 | 1665 | ||
1590 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; | 1666 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; |
@@ -1686,13 +1762,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1686 | } | 1762 | } |
1687 | 1763 | ||
1688 | 1764 | ||
1689 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
1690 | /* Want receive buffer size to be multiple of 64 bits | 1765 | /* Want receive buffer size to be multiple of 64 bits |
1691 | * and incl room for vlan and truncation | 1766 | * and incl room for vlan and truncation |
1692 | */ | 1767 | */ |
1693 | static inline unsigned sky2_buf_size(int mtu) | 1768 | static inline unsigned sky2_buf_size(int mtu) |
1694 | { | 1769 | { |
1695 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1770 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
1696 | } | 1771 | } |
1697 | 1772 | ||
1698 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1773 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -1857,39 +1932,38 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1857 | } | 1932 | } |
1858 | } | 1933 | } |
1859 | 1934 | ||
1935 | /* Is status ring empty or is there more to do? */ | ||
1936 | static inline int sky2_more_work(const struct sky2_hw *hw) | ||
1937 | { | ||
1938 | return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); | ||
1939 | } | ||
1940 | |||
1860 | /* Process status response ring */ | 1941 | /* Process status response ring */ |
1861 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1942 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1862 | { | 1943 | { |
1863 | int work_done = 0; | 1944 | int work_done = 0; |
1945 | u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1864 | 1946 | ||
1865 | rmb(); | 1947 | rmb(); |
1866 | 1948 | ||
1867 | for(;;) { | 1949 | while (hw->st_idx != hwidx) { |
1868 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1950 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
1869 | struct net_device *dev; | 1951 | struct net_device *dev; |
1870 | struct sky2_port *sky2; | 1952 | struct sky2_port *sky2; |
1871 | struct sk_buff *skb; | 1953 | struct sk_buff *skb; |
1872 | u32 status; | 1954 | u32 status; |
1873 | u16 length; | 1955 | u16 length; |
1874 | u8 link, opcode; | ||
1875 | 1956 | ||
1876 | opcode = le->opcode; | 1957 | hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); |
1877 | if (!opcode) | ||
1878 | break; | ||
1879 | opcode &= ~HW_OWNER; | ||
1880 | 1958 | ||
1881 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; | 1959 | BUG_ON(le->link >= 2); |
1882 | le->opcode = 0; | 1960 | dev = hw->dev[le->link]; |
1883 | |||
1884 | link = le->link; | ||
1885 | BUG_ON(link >= 2); | ||
1886 | dev = hw->dev[link]; | ||
1887 | 1961 | ||
1888 | sky2 = netdev_priv(dev); | 1962 | sky2 = netdev_priv(dev); |
1889 | length = le->length; | 1963 | length = le->length; |
1890 | status = le->status; | 1964 | status = le->status; |
1891 | 1965 | ||
1892 | switch (opcode) { | 1966 | switch (le->opcode & ~HW_OWNER) { |
1893 | case OP_RXSTAT: | 1967 | case OP_RXSTAT: |
1894 | skb = sky2_receive(sky2, length, status); | 1968 | skb = sky2_receive(sky2, length, status); |
1895 | if (!skb) | 1969 | if (!skb) |
@@ -1929,7 +2003,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
1929 | 2003 | ||
1930 | case OP_TXINDEXLE: | 2004 | case OP_TXINDEXLE: |
1931 | /* TX index reports status for both ports */ | 2005 | /* TX index reports status for both ports */ |
1932 | sky2_tx_done(hw->dev[0], status & 0xffff); | 2006 | BUILD_BUG_ON(TX_RING_SIZE > 0x1000); |
2007 | sky2_tx_done(hw->dev[0], status & 0xfff); | ||
1933 | if (hw->dev[1]) | 2008 | if (hw->dev[1]) |
1934 | sky2_tx_done(hw->dev[1], | 2009 | sky2_tx_done(hw->dev[1], |
1935 | ((status >> 24) & 0xff) | 2010 | ((status >> 24) & 0xff) |
@@ -1939,8 +2014,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
1939 | default: | 2014 | default: |
1940 | if (net_ratelimit()) | 2015 | if (net_ratelimit()) |
1941 | printk(KERN_WARNING PFX | 2016 | printk(KERN_WARNING PFX |
1942 | "unknown status opcode 0x%x\n", opcode); | 2017 | "unknown status opcode 0x%x\n", le->opcode); |
1943 | break; | 2018 | goto exit_loop; |
1944 | } | 2019 | } |
1945 | } | 2020 | } |
1946 | 2021 | ||
@@ -2086,6 +2161,21 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2086 | } | 2161 | } |
2087 | } | 2162 | } |
2088 | 2163 | ||
2164 | /* If idle then force a fake soft NAPI poll once a second | ||
2165 | * to work around cases where sharing an edge triggered interrupt. | ||
2166 | */ | ||
2167 | static void sky2_idle(unsigned long arg) | ||
2168 | { | ||
2169 | struct sky2_hw *hw = (struct sky2_hw *) arg; | ||
2170 | struct net_device *dev = hw->dev[0]; | ||
2171 | |||
2172 | if (__netif_rx_schedule_prep(dev)) | ||
2173 | __netif_rx_schedule(dev); | ||
2174 | |||
2175 | mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); | ||
2176 | } | ||
2177 | |||
2178 | |||
2089 | static int sky2_poll(struct net_device *dev0, int *budget) | 2179 | static int sky2_poll(struct net_device *dev0, int *budget) |
2090 | { | 2180 | { |
2091 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2181 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
@@ -2093,49 +2183,46 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2093 | int work_done = 0; | 2183 | int work_done = 0; |
2094 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2184 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2095 | 2185 | ||
2096 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2186 | if (status & Y2_IS_HW_ERR) |
2097 | if (status & Y2_IS_HW_ERR) | 2187 | sky2_hw_intr(hw); |
2098 | sky2_hw_intr(hw); | ||
2099 | |||
2100 | if (status & Y2_IS_IRQ_PHY1) | ||
2101 | sky2_phy_intr(hw, 0); | ||
2102 | 2188 | ||
2103 | if (status & Y2_IS_IRQ_PHY2) | 2189 | if (status & Y2_IS_IRQ_PHY1) |
2104 | sky2_phy_intr(hw, 1); | 2190 | sky2_phy_intr(hw, 0); |
2105 | 2191 | ||
2106 | if (status & Y2_IS_IRQ_MAC1) | 2192 | if (status & Y2_IS_IRQ_PHY2) |
2107 | sky2_mac_intr(hw, 0); | 2193 | sky2_phy_intr(hw, 1); |
2108 | 2194 | ||
2109 | if (status & Y2_IS_IRQ_MAC2) | 2195 | if (status & Y2_IS_IRQ_MAC1) |
2110 | sky2_mac_intr(hw, 1); | 2196 | sky2_mac_intr(hw, 0); |
2111 | 2197 | ||
2112 | if (status & Y2_IS_CHK_RX1) | 2198 | if (status & Y2_IS_IRQ_MAC2) |
2113 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); | 2199 | sky2_mac_intr(hw, 1); |
2114 | 2200 | ||
2115 | if (status & Y2_IS_CHK_RX2) | 2201 | if (status & Y2_IS_CHK_RX1) |
2116 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); | 2202 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); |
2117 | 2203 | ||
2118 | if (status & Y2_IS_CHK_TXA1) | 2204 | if (status & Y2_IS_CHK_RX2) |
2119 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); | 2205 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); |
2120 | 2206 | ||
2121 | if (status & Y2_IS_CHK_TXA2) | 2207 | if (status & Y2_IS_CHK_TXA1) |
2122 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2208 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); |
2123 | } | ||
2124 | 2209 | ||
2125 | if (status & Y2_IS_STAT_BMU) { | 2210 | if (status & Y2_IS_CHK_TXA2) |
2126 | work_done = sky2_status_intr(hw, work_limit); | 2211 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
2127 | *budget -= work_done; | ||
2128 | dev0->quota -= work_done; | ||
2129 | 2212 | ||
2130 | if (work_done >= work_limit) | 2213 | work_done = sky2_status_intr(hw, work_limit); |
2131 | return 1; | 2214 | *budget -= work_done; |
2215 | dev0->quota -= work_done; | ||
2132 | 2216 | ||
2217 | if (status & Y2_IS_STAT_BMU) | ||
2133 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2218 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2134 | } | 2219 | |
2220 | if (sky2_more_work(hw)) | ||
2221 | return 1; | ||
2135 | 2222 | ||
2136 | netif_rx_complete(dev0); | 2223 | netif_rx_complete(dev0); |
2137 | 2224 | ||
2138 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2225 | sky2_read32(hw, B0_Y2_SP_LISR); |
2139 | return 0; | 2226 | return 0; |
2140 | } | 2227 | } |
2141 | 2228 | ||
@@ -2153,8 +2240,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2153 | prefetch(&hw->st_le[hw->st_idx]); | 2240 | prefetch(&hw->st_le[hw->st_idx]); |
2154 | if (likely(__netif_rx_schedule_prep(dev0))) | 2241 | if (likely(__netif_rx_schedule_prep(dev0))) |
2155 | __netif_rx_schedule(dev0); | 2242 | __netif_rx_schedule(dev0); |
2156 | else | ||
2157 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
2158 | 2243 | ||
2159 | return IRQ_HANDLED; | 2244 | return IRQ_HANDLED; |
2160 | } | 2245 | } |
@@ -2193,7 +2278,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2193 | } | 2278 | } |
2194 | 2279 | ||
2195 | 2280 | ||
2196 | static int sky2_reset(struct sky2_hw *hw) | 2281 | static int __devinit sky2_reset(struct sky2_hw *hw) |
2197 | { | 2282 | { |
2198 | u16 status; | 2283 | u16 status; |
2199 | u8 t8, pmd_type; | 2284 | u8 t8, pmd_type; |
@@ -2218,13 +2303,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2218 | return -EOPNOTSUPP; | 2303 | return -EOPNOTSUPP; |
2219 | } | 2304 | } |
2220 | 2305 | ||
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 */ | 2306 | /* disable ASF */ |
2229 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2307 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2230 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2308 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
@@ -3028,12 +3106,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3028 | sky2->duplex = -1; | 3106 | sky2->duplex = -1; |
3029 | sky2->speed = -1; | 3107 | sky2->speed = -1; |
3030 | sky2->advertising = sky2_supported_modes(hw); | 3108 | sky2->advertising = sky2_supported_modes(hw); |
3031 | 3109 | sky2->rx_csum = 1; | |
3032 | /* Receive checksum disabled for Yukon XL | ||
3033 | * because of observed problems with incorrect | ||
3034 | * values when multiple packets are received in one interrupt | ||
3035 | */ | ||
3036 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | ||
3037 | 3110 | ||
3038 | spin_lock_init(&sky2->phy_lock); | 3111 | spin_lock_init(&sky2->phy_lock); |
3039 | sky2->tx_pending = TX_DEF_PENDING; | 3112 | sky2->tx_pending = TX_DEF_PENDING; |
@@ -3276,6 +3349,11 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3276 | 3349 | ||
3277 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3350 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3278 | 3351 | ||
3352 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | ||
3353 | if (idle_timeout > 0) | ||
3354 | mod_timer(&hw->idle_timer, | ||
3355 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
3356 | |||
3279 | pci_set_drvdata(pdev, hw); | 3357 | pci_set_drvdata(pdev, hw); |
3280 | 3358 | ||
3281 | return 0; | 3359 | return 0; |
@@ -3311,13 +3389,17 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3311 | if (!hw) | 3389 | if (!hw) |
3312 | return; | 3390 | return; |
3313 | 3391 | ||
3392 | del_timer_sync(&hw->idle_timer); | ||
3393 | |||
3394 | sky2_write32(hw, B0_IMSK, 0); | ||
3395 | synchronize_irq(hw->pdev->irq); | ||
3396 | |||
3314 | dev0 = hw->dev[0]; | 3397 | dev0 = hw->dev[0]; |
3315 | dev1 = hw->dev[1]; | 3398 | dev1 = hw->dev[1]; |
3316 | if (dev1) | 3399 | if (dev1) |
3317 | unregister_netdev(dev1); | 3400 | unregister_netdev(dev1); |
3318 | unregister_netdev(dev0); | 3401 | unregister_netdev(dev0); |
3319 | 3402 | ||
3320 | sky2_write32(hw, B0_IMSK, 0); | ||
3321 | sky2_set_power_state(hw, PCI_D3hot); | 3403 | sky2_set_power_state(hw, PCI_D3hot); |
3322 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3404 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
3323 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3405 | sky2_write8(hw, B0_CTST, CS_RST_SET); |