diff options
| author | Steve French <sfrench@us.ibm.com> | 2006-03-03 06:27:25 -0500 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2006-03-03 06:27:25 -0500 |
| commit | c6ee60b7c8bbc78e3b1776b2820a7e7f95f8996a (patch) | |
| tree | 99b48ef0f5217fddc0aa897d9e60d95ace7da6ff /drivers/net/sky2.c | |
| parent | 13298defe5323c7fdcac268f588d8d1090758fb8 (diff) | |
| parent | c499ec24c31edf270e777a868ffd0daddcfe7ebd (diff) | |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'drivers/net/sky2.c')
| -rw-r--r-- | drivers/net/sky2.c | 250 |
1 files changed, 104 insertions, 146 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index bfeba5b9cd7a..72c1630977d6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -96,10 +96,6 @@ static int copybreak __read_mostly = 256; | |||
| 96 | module_param(copybreak, int, 0); | 96 | module_param(copybreak, int, 0); |
| 97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); | 97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); |
| 98 | 98 | ||
| 99 | static int disable_msi = 0; | ||
| 100 | module_param(disable_msi, int, 0); | ||
| 101 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | ||
| 102 | |||
| 103 | static const struct pci_device_id sky2_id_table[] = { | 99 | static const struct pci_device_id sky2_id_table[] = { |
| 104 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
| 105 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
| @@ -195,11 +191,11 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
| 195 | pr_debug("sky2_set_power_state %d\n", state); | 191 | pr_debug("sky2_set_power_state %d\n", state); |
| 196 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 192 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
| 197 | 193 | ||
| 198 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); | 194 | power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_PMC); |
| 199 | vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && | 195 | vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && |
| 200 | (power_control & PCI_PM_CAP_PME_D3cold); | 196 | (power_control & PCI_PM_CAP_PME_D3cold); |
| 201 | 197 | ||
| 202 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); | 198 | power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL); |
| 203 | 199 | ||
| 204 | power_control |= PCI_PM_CTRL_PME_STATUS; | 200 | power_control |= PCI_PM_CTRL_PME_STATUS; |
| 205 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); | 201 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); |
| @@ -223,7 +219,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
| 223 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | 219 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); |
| 224 | 220 | ||
| 225 | /* Turn off phy power saving */ | 221 | /* Turn off phy power saving */ |
| 226 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); | 222 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); |
| 227 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | 223 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); |
| 228 | 224 | ||
| 229 | /* looks like this XL is back asswards .. */ | 225 | /* looks like this XL is back asswards .. */ |
| @@ -232,18 +228,28 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
| 232 | if (hw->ports > 1) | 228 | if (hw->ports > 1) |
| 233 | reg1 |= PCI_Y2_PHY2_COMA; | 229 | reg1 |= PCI_Y2_PHY2_COMA; |
| 234 | } | 230 | } |
| 235 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); | 231 | |
| 232 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | ||
| 233 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | ||
| 234 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); | ||
| 235 | reg1 &= P_ASPM_CONTROL_MSK; | ||
| 236 | sky2_pci_write32(hw, PCI_DEV_REG4, reg1); | ||
| 237 | sky2_pci_write32(hw, PCI_DEV_REG5, 0); | ||
| 238 | } | ||
| 239 | |||
| 240 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); | ||
| 241 | |||
| 236 | break; | 242 | break; |
| 237 | 243 | ||
| 238 | case PCI_D3hot: | 244 | case PCI_D3hot: |
| 239 | case PCI_D3cold: | 245 | case PCI_D3cold: |
| 240 | /* Turn on phy power saving */ | 246 | /* Turn on phy power saving */ |
| 241 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); | 247 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); |
| 242 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | 248 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) |
| 243 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | 249 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); |
| 244 | else | 250 | else |
| 245 | reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | 251 | reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); |
| 246 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); | 252 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); |
| 247 | 253 | ||
| 248 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | 254 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) |
| 249 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | 255 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); |
| @@ -265,7 +271,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
| 265 | ret = -1; | 271 | ret = -1; |
| 266 | } | 272 | } |
| 267 | 273 | ||
| 268 | pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control); | 274 | sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control); |
| 269 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 275 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
| 270 | return ret; | 276 | return ret; |
| 271 | } | 277 | } |
| @@ -463,16 +469,31 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
| 463 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); | 469 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); |
| 464 | } | 470 | } |
| 465 | 471 | ||
| 466 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 472 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) { |
| 473 | /* apply fixes in PHY AFE */ | ||
| 474 | gm_phy_write(hw, port, 22, 255); | ||
| 475 | /* increase differential signal amplitude in 10BASE-T */ | ||
| 476 | gm_phy_write(hw, port, 24, 0xaa99); | ||
| 477 | gm_phy_write(hw, port, 23, 0x2011); | ||
| 467 | 478 | ||
| 468 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { | 479 | /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ |
| 469 | /* turn on 100 Mbps LED (LED_LINK100) */ | 480 | gm_phy_write(hw, port, 24, 0xa204); |
| 470 | ledover |= PHY_M_LED_MO_100(MO_LED_ON); | 481 | gm_phy_write(hw, port, 23, 0x2002); |
| 471 | } | ||
| 472 | 482 | ||
| 473 | if (ledover) | 483 | /* set page register to 0 */ |
| 474 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | 484 | gm_phy_write(hw, port, 22, 0); |
| 485 | } else { | ||
| 486 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | ||
| 487 | |||
| 488 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { | ||
| 489 | /* turn on 100 Mbps LED (LED_LINK100) */ | ||
| 490 | ledover |= PHY_M_LED_MO_100(MO_LED_ON); | ||
| 491 | } | ||
| 492 | |||
| 493 | if (ledover) | ||
| 494 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | ||
| 475 | 495 | ||
| 496 | } | ||
| 476 | /* Enable phy interrupt on auto-negotiation complete (or link up) */ | 497 | /* Enable phy interrupt on auto-negotiation complete (or link up) */ |
| 477 | if (sky2->autoneg == AUTONEG_ENABLE) | 498 | if (sky2->autoneg == AUTONEG_ENABLE) |
| 478 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); | 499 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); |
| @@ -953,6 +974,12 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
| 953 | 974 | ||
| 954 | sky2->rx_put = sky2->rx_next = 0; | 975 | sky2->rx_put = sky2->rx_next = 0; |
| 955 | sky2_qset(hw, rxq); | 976 | sky2_qset(hw, rxq); |
| 977 | |||
| 978 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) { | ||
| 979 | /* MAC Rx RAM Read is controlled by hardware */ | ||
| 980 | sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS); | ||
| 981 | } | ||
| 982 | |||
| 956 | sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); | 983 | sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); |
| 957 | 984 | ||
| 958 | rx_set_checksum(sky2); | 985 | rx_set_checksum(sky2); |
| @@ -1035,9 +1062,10 @@ static int sky2_up(struct net_device *dev) | |||
| 1035 | RB_RST_SET); | 1062 | RB_RST_SET); |
| 1036 | 1063 | ||
| 1037 | sky2_qset(hw, txqaddr[port]); | 1064 | sky2_qset(hw, txqaddr[port]); |
| 1038 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) | ||
| 1039 | sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0); | ||
| 1040 | 1065 | ||
| 1066 | /* Set almost empty threshold */ | ||
| 1067 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == 1) | ||
| 1068 | sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0); | ||
| 1041 | 1069 | ||
| 1042 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, | 1070 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, |
| 1043 | TX_RING_SIZE - 1); | 1071 | TX_RING_SIZE - 1); |
| @@ -1047,8 +1075,10 @@ static int sky2_up(struct net_device *dev) | |||
| 1047 | goto err_out; | 1075 | goto err_out; |
| 1048 | 1076 | ||
| 1049 | /* Enable interrupts from phy/mac for port */ | 1077 | /* Enable interrupts from phy/mac for port */ |
| 1078 | spin_lock_irq(&hw->hw_lock); | ||
| 1050 | hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1079 | hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; |
| 1051 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1080 | sky2_write32(hw, B0_IMSK, hw->intr_mask); |
| 1081 | spin_unlock_irq(&hw->hw_lock); | ||
| 1052 | return 0; | 1082 | return 0; |
| 1053 | 1083 | ||
| 1054 | err_out: | 1084 | err_out: |
| @@ -1348,10 +1378,10 @@ static int sky2_down(struct net_device *dev) | |||
| 1348 | netif_stop_queue(dev); | 1378 | netif_stop_queue(dev); |
| 1349 | 1379 | ||
| 1350 | /* Disable port IRQ */ | 1380 | /* Disable port IRQ */ |
| 1351 | local_irq_disable(); | 1381 | spin_lock_irq(&hw->hw_lock); |
| 1352 | hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | 1382 | hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); |
| 1353 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1383 | sky2_write32(hw, B0_IMSK, hw->intr_mask); |
| 1354 | local_irq_enable(); | 1384 | spin_unlock_irq(&hw->hw_lock); |
| 1355 | 1385 | ||
| 1356 | flush_scheduled_work(); | 1386 | flush_scheduled_work(); |
| 1357 | 1387 | ||
| @@ -1633,10 +1663,10 @@ static void sky2_phy_task(void *arg) | |||
| 1633 | out: | 1663 | out: |
| 1634 | up(&sky2->phy_sema); | 1664 | up(&sky2->phy_sema); |
| 1635 | 1665 | ||
| 1636 | local_irq_disable(); | 1666 | spin_lock_irq(&hw->hw_lock); |
| 1637 | hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; | 1667 | hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; |
| 1638 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1668 | sky2_write32(hw, B0_IMSK, hw->intr_mask); |
| 1639 | local_irq_enable(); | 1669 | spin_unlock_irq(&hw->hw_lock); |
| 1640 | } | 1670 | } |
| 1641 | 1671 | ||
| 1642 | 1672 | ||
| @@ -1863,6 +1893,17 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 1863 | 1893 | ||
| 1864 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 1894 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
| 1865 | 1895 | ||
| 1896 | /* | ||
| 1897 | * Kick the STAT_LEV_TIMER_CTRL timer. | ||
| 1898 | * This fixes my hangs on Yukon-EC (0xb6) rev 1. | ||
| 1899 | * The if clause is there to start the timer only if it has been | ||
| 1900 | * configured correctly and not been disabled via ethtool. | ||
| 1901 | */ | ||
| 1902 | if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) { | ||
| 1903 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP); | ||
| 1904 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); | ||
| 1905 | } | ||
| 1906 | |||
| 1866 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | 1907 | hwidx = sky2_read16(hw, STAT_PUT_IDX); |
| 1867 | BUG_ON(hwidx >= STATUS_RING_SIZE); | 1908 | BUG_ON(hwidx >= STATUS_RING_SIZE); |
| 1868 | rmb(); | 1909 | rmb(); |
| @@ -1945,16 +1986,19 @@ exit_loop: | |||
| 1945 | sky2_tx_check(hw, 0, tx_done[0]); | 1986 | sky2_tx_check(hw, 0, tx_done[0]); |
| 1946 | sky2_tx_check(hw, 1, tx_done[1]); | 1987 | sky2_tx_check(hw, 1, tx_done[1]); |
| 1947 | 1988 | ||
| 1989 | if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { | ||
| 1990 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
| 1991 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
| 1992 | } | ||
| 1993 | |||
| 1948 | if (likely(work_done < to_do)) { | 1994 | if (likely(work_done < to_do)) { |
| 1949 | /* need to restart TX timer */ | 1995 | spin_lock_irq(&hw->hw_lock); |
| 1950 | if (is_ec_a1(hw)) { | 1996 | __netif_rx_complete(dev0); |
| 1951 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
| 1952 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
| 1953 | } | ||
| 1954 | 1997 | ||
| 1955 | netif_rx_complete(dev0); | ||
| 1956 | hw->intr_mask |= Y2_IS_STAT_BMU; | 1998 | hw->intr_mask |= Y2_IS_STAT_BMU; |
| 1957 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1999 | sky2_write32(hw, B0_IMSK, hw->intr_mask); |
| 2000 | spin_unlock_irq(&hw->hw_lock); | ||
| 2001 | |||
| 1958 | return 0; | 2002 | return 0; |
| 1959 | } else { | 2003 | } else { |
| 1960 | *budget -= work_done; | 2004 | *budget -= work_done; |
| @@ -2017,13 +2061,13 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
| 2017 | if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { | 2061 | if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { |
| 2018 | u16 pci_err; | 2062 | u16 pci_err; |
| 2019 | 2063 | ||
| 2020 | pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err); | 2064 | pci_err = sky2_pci_read16(hw, PCI_STATUS); |
| 2021 | if (net_ratelimit()) | 2065 | if (net_ratelimit()) |
| 2022 | printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n", | 2066 | printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n", |
| 2023 | pci_name(hw->pdev), pci_err); | 2067 | pci_name(hw->pdev), pci_err); |
| 2024 | 2068 | ||
| 2025 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2069 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
| 2026 | pci_write_config_word(hw->pdev, PCI_STATUS, | 2070 | sky2_pci_write16(hw, PCI_STATUS, |
| 2027 | pci_err | PCI_STATUS_ERROR_BITS); | 2071 | pci_err | PCI_STATUS_ERROR_BITS); |
| 2028 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 2072 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
| 2029 | } | 2073 | } |
| @@ -2032,7 +2076,7 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
| 2032 | /* PCI-Express uncorrectable Error occurred */ | 2076 | /* PCI-Express uncorrectable Error occurred */ |
| 2033 | u32 pex_err; | 2077 | u32 pex_err; |
| 2034 | 2078 | ||
| 2035 | pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err); | 2079 | pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT); |
| 2036 | 2080 | ||
| 2037 | if (net_ratelimit()) | 2081 | if (net_ratelimit()) |
| 2038 | printk(KERN_ERR PFX "%s: pci express error (0x%x)\n", | 2082 | printk(KERN_ERR PFX "%s: pci express error (0x%x)\n", |
| @@ -2040,7 +2084,7 @@ static void sky2_hw_intr(struct sky2_hw *hw) | |||
| 2040 | 2084 | ||
| 2041 | /* clear the interrupt */ | 2085 | /* clear the interrupt */ |
| 2042 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2086 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
| 2043 | pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, | 2087 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, |
| 2044 | 0xffffffffUL); | 2088 | 0xffffffffUL); |
| 2045 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 2089 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
| 2046 | 2090 | ||
| @@ -2086,6 +2130,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) | |||
| 2086 | 2130 | ||
| 2087 | hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | 2131 | hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); |
| 2088 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 2132 | sky2_write32(hw, B0_IMSK, hw->intr_mask); |
| 2133 | |||
| 2089 | schedule_work(&sky2->phy_task); | 2134 | schedule_work(&sky2->phy_task); |
| 2090 | } | 2135 | } |
| 2091 | 2136 | ||
| @@ -2099,6 +2144,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
| 2099 | if (status == 0 || status == ~0) | 2144 | if (status == 0 || status == ~0) |
| 2100 | return IRQ_NONE; | 2145 | return IRQ_NONE; |
| 2101 | 2146 | ||
| 2147 | spin_lock(&hw->hw_lock); | ||
| 2102 | if (status & Y2_IS_HW_ERR) | 2148 | if (status & Y2_IS_HW_ERR) |
| 2103 | sky2_hw_intr(hw); | 2149 | sky2_hw_intr(hw); |
| 2104 | 2150 | ||
| @@ -2127,7 +2173,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
| 2127 | 2173 | ||
| 2128 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | 2174 | sky2_write32(hw, B0_Y2_SP_ICR, 2); |
| 2129 | 2175 | ||
| 2130 | sky2_read32(hw, B0_IMSK); | 2176 | spin_unlock(&hw->hw_lock); |
| 2131 | 2177 | ||
| 2132 | return IRQ_HANDLED; | 2178 | return IRQ_HANDLED; |
| 2133 | } | 2179 | } |
| @@ -2170,7 +2216,7 @@ static int sky2_reset(struct sky2_hw *hw) | |||
| 2170 | { | 2216 | { |
| 2171 | u16 status; | 2217 | u16 status; |
| 2172 | u8 t8, pmd_type; | 2218 | u8 t8, pmd_type; |
| 2173 | int i, err; | 2219 | int i; |
| 2174 | 2220 | ||
| 2175 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2221 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
| 2176 | 2222 | ||
| @@ -2192,25 +2238,18 @@ static int sky2_reset(struct sky2_hw *hw) | |||
| 2192 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2238 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
| 2193 | 2239 | ||
| 2194 | /* clear PCI errors, if any */ | 2240 | /* clear PCI errors, if any */ |
| 2195 | err = pci_read_config_word(hw->pdev, PCI_STATUS, &status); | 2241 | status = sky2_pci_read16(hw, PCI_STATUS); |
| 2196 | if (err) | ||
| 2197 | goto pci_err; | ||
| 2198 | 2242 | ||
| 2199 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 2243 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
| 2200 | err = pci_write_config_word(hw->pdev, PCI_STATUS, | 2244 | sky2_pci_write16(hw, PCI_STATUS, status | PCI_STATUS_ERROR_BITS); |
| 2201 | status | PCI_STATUS_ERROR_BITS); | 2245 | |
| 2202 | if (err) | ||
| 2203 | goto pci_err; | ||
| 2204 | 2246 | ||
| 2205 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); | 2247 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); |
| 2206 | 2248 | ||
| 2207 | /* clear any PEX errors */ | 2249 | /* clear any PEX errors */ |
| 2208 | if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) { | 2250 | if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) |
| 2209 | err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, | 2251 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); |
| 2210 | 0xffffffffUL); | 2252 | |
| 2211 | if (err) | ||
| 2212 | goto pci_err; | ||
| 2213 | } | ||
| 2214 | 2253 | ||
| 2215 | pmd_type = sky2_read8(hw, B2_PMD_TYP); | 2254 | pmd_type = sky2_read8(hw, B2_PMD_TYP); |
| 2216 | hw->copper = !(pmd_type == 'L' || pmd_type == 'S'); | 2255 | hw->copper = !(pmd_type == 'L' || pmd_type == 'S'); |
| @@ -2309,8 +2348,7 @@ static int sky2_reset(struct sky2_hw *hw) | |||
| 2309 | sky2_write8(hw, STAT_FIFO_ISR_WM, 16); | 2348 | sky2_write8(hw, STAT_FIFO_ISR_WM, 16); |
| 2310 | 2349 | ||
| 2311 | sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); | 2350 | sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); |
| 2312 | sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100)); | 2351 | sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7)); |
| 2313 | sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20)); | ||
| 2314 | } | 2352 | } |
| 2315 | 2353 | ||
| 2316 | /* enable status unit */ | 2354 | /* enable status unit */ |
| @@ -2321,14 +2359,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
| 2321 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 2359 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
| 2322 | 2360 | ||
| 2323 | return 0; | 2361 | return 0; |
| 2324 | |||
| 2325 | pci_err: | ||
| 2326 | /* This is to catch a BIOS bug workaround where | ||
| 2327 | * mmconfig table doesn't have other buses. | ||
| 2328 | */ | ||
| 2329 | printk(KERN_ERR PFX "%s: can't access PCI config space\n", | ||
| 2330 | pci_name(hw->pdev)); | ||
| 2331 | return err; | ||
| 2332 | } | 2362 | } |
| 2333 | 2363 | ||
| 2334 | static u32 sky2_supported_modes(const struct sky2_hw *hw) | 2364 | static u32 sky2_supported_modes(const struct sky2_hw *hw) |
| @@ -2852,11 +2882,11 @@ static int sky2_set_coalesce(struct net_device *dev, | |||
| 2852 | (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax)) | 2882 | (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax)) |
| 2853 | return -EINVAL; | 2883 | return -EINVAL; |
| 2854 | 2884 | ||
| 2855 | if (ecmd->tx_max_coalesced_frames > 0xffff) | 2885 | if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1) |
| 2856 | return -EINVAL; | 2886 | return -EINVAL; |
| 2857 | if (ecmd->rx_max_coalesced_frames > 0xff) | 2887 | if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING) |
| 2858 | return -EINVAL; | 2888 | return -EINVAL; |
| 2859 | if (ecmd->rx_max_coalesced_frames_irq > 0xff) | 2889 | if (ecmd->rx_max_coalesced_frames_irq >RX_MAX_PENDING) |
| 2860 | return -EINVAL; | 2890 | return -EINVAL; |
| 2861 | 2891 | ||
| 2862 | if (ecmd->tx_coalesce_usecs == 0) | 2892 | if (ecmd->tx_coalesce_usecs == 0) |
| @@ -3092,61 +3122,6 @@ static void __devinit sky2_show_addr(struct net_device *dev) | |||
| 3092 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); | 3122 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); |
| 3093 | } | 3123 | } |
| 3094 | 3124 | ||
| 3095 | /* Handle software interrupt used during MSI test */ | ||
| 3096 | static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, | ||
| 3097 | struct pt_regs *regs) | ||
| 3098 | { | ||
| 3099 | struct sky2_hw *hw = dev_id; | ||
| 3100 | u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
| 3101 | |||
| 3102 | if (status == 0) | ||
| 3103 | return IRQ_NONE; | ||
| 3104 | |||
| 3105 | if (status & Y2_IS_IRQ_SW) { | ||
| 3106 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
| 3107 | hw->msi = 1; | ||
| 3108 | } | ||
| 3109 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | ||
| 3110 | |||
| 3111 | sky2_read32(hw, B0_IMSK); | ||
| 3112 | return IRQ_HANDLED; | ||
| 3113 | } | ||
| 3114 | |||
| 3115 | /* Test interrupt path by forcing a a software IRQ */ | ||
| 3116 | static int __devinit sky2_test_msi(struct sky2_hw *hw) | ||
| 3117 | { | ||
| 3118 | struct pci_dev *pdev = hw->pdev; | ||
| 3119 | int i, err; | ||
| 3120 | |||
| 3121 | sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); | ||
| 3122 | |||
| 3123 | err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); | ||
| 3124 | if (err) { | ||
| 3125 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | ||
| 3126 | pci_name(pdev), pdev->irq); | ||
| 3127 | return err; | ||
| 3128 | } | ||
| 3129 | |||
| 3130 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); | ||
| 3131 | wmb(); | ||
| 3132 | |||
| 3133 | for (i = 0; i < 10; i++) { | ||
| 3134 | barrier(); | ||
| 3135 | if (hw->msi) | ||
| 3136 | goto found; | ||
| 3137 | mdelay(1); | ||
| 3138 | } | ||
| 3139 | |||
| 3140 | err = -EOPNOTSUPP; | ||
| 3141 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
| 3142 | found: | ||
| 3143 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3144 | |||
| 3145 | free_irq(pdev->irq, hw); | ||
| 3146 | |||
| 3147 | return err; | ||
| 3148 | } | ||
| 3149 | |||
| 3150 | static int __devinit sky2_probe(struct pci_dev *pdev, | 3125 | static int __devinit sky2_probe(struct pci_dev *pdev, |
| 3151 | const struct pci_device_id *ent) | 3126 | const struct pci_device_id *ent) |
| 3152 | { | 3127 | { |
| @@ -3198,17 +3173,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3198 | } | 3173 | } |
| 3199 | } | 3174 | } |
| 3200 | 3175 | ||
| 3201 | #ifdef __BIG_ENDIAN | ||
| 3202 | /* byte swap descriptors in hardware */ | ||
| 3203 | { | ||
| 3204 | u32 reg; | ||
| 3205 | |||
| 3206 | pci_read_config_dword(pdev, PCI_DEV_REG2, ®); | ||
| 3207 | reg |= PCI_REV_DESC; | ||
| 3208 | pci_write_config_dword(pdev, PCI_DEV_REG2, reg); | ||
| 3209 | } | ||
| 3210 | #endif | ||
| 3211 | |||
| 3212 | err = -ENOMEM; | 3176 | err = -ENOMEM; |
| 3213 | hw = kzalloc(sizeof(*hw), GFP_KERNEL); | 3177 | hw = kzalloc(sizeof(*hw), GFP_KERNEL); |
| 3214 | if (!hw) { | 3178 | if (!hw) { |
| @@ -3226,6 +3190,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3226 | goto err_out_free_hw; | 3190 | goto err_out_free_hw; |
| 3227 | } | 3191 | } |
| 3228 | hw->pm_cap = pm_cap; | 3192 | hw->pm_cap = pm_cap; |
| 3193 | spin_lock_init(&hw->hw_lock); | ||
| 3194 | |||
| 3195 | #ifdef __BIG_ENDIAN | ||
| 3196 | /* byte swap descriptors in hardware */ | ||
| 3197 | { | ||
| 3198 | u32 reg; | ||
| 3199 | |||
| 3200 | reg = sky2_pci_read32(hw, PCI_DEV_REG2); | ||
| 3201 | reg |= PCI_REV_DESC; | ||
| 3202 | sky2_pci_write32(hw, PCI_DEV_REG2, reg); | ||
| 3203 | } | ||
| 3204 | #endif | ||
| 3229 | 3205 | ||
| 3230 | /* ring for status responses */ | 3206 | /* ring for status responses */ |
| 3231 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, | 3207 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, |
| @@ -3267,20 +3243,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3267 | } | 3243 | } |
| 3268 | } | 3244 | } |
| 3269 | 3245 | ||
| 3270 | if (!disable_msi && pci_enable_msi(pdev) == 0) { | ||
| 3271 | err = sky2_test_msi(hw); | ||
| 3272 | if (err == -EOPNOTSUPP) { | ||
| 3273 | /* MSI test failed, go back to INTx mode */ | ||
| 3274 | printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " | ||
| 3275 | "switching to INTx mode. Please report this failure to " | ||
| 3276 | "the PCI maintainer and include system chipset information.\n", | ||
| 3277 | pci_name(pdev)); | ||
| 3278 | pci_disable_msi(pdev); | ||
| 3279 | } | ||
| 3280 | else if (err) | ||
| 3281 | goto err_out_unregister; | ||
| 3282 | } | ||
| 3283 | |||
| 3284 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, | 3246 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, |
| 3285 | DRV_NAME, hw); | 3247 | DRV_NAME, hw); |
| 3286 | if (err) { | 3248 | if (err) { |
| @@ -3297,8 +3259,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3297 | return 0; | 3259 | return 0; |
| 3298 | 3260 | ||
| 3299 | err_out_unregister: | 3261 | err_out_unregister: |
| 3300 | if (hw->msi) | ||
| 3301 | pci_disable_msi(pdev); | ||
| 3302 | if (dev1) { | 3262 | if (dev1) { |
| 3303 | unregister_netdev(dev1); | 3263 | unregister_netdev(dev1); |
| 3304 | free_netdev(dev1); | 3264 | free_netdev(dev1); |
| @@ -3341,8 +3301,6 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 3341 | sky2_read8(hw, B0_CTST); | 3301 | sky2_read8(hw, B0_CTST); |
| 3342 | 3302 | ||
| 3343 | free_irq(pdev->irq, hw); | 3303 | free_irq(pdev->irq, hw); |
| 3344 | if (hw->msi) | ||
| 3345 | pci_disable_msi(pdev); | ||
| 3346 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 3304 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
| 3347 | pci_release_regions(pdev); | 3305 | pci_release_regions(pdev); |
| 3348 | pci_disable_device(pdev); | 3306 | pci_disable_device(pdev); |
