diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 114 |
1 files changed, 82 insertions, 32 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ffd267fab21d..97fe95666f3b 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.3" | 54 | #define DRV_VERSION "1.4" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -105,6 +105,7 @@ MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms) | |||
105 | static const struct pci_device_id sky2_id_table[] = { | 105 | static const struct pci_device_id sky2_id_table[] = { |
106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
107 | { 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 */ | ||
108 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, | 109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, |
109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, | 110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, |
110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, | 111 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, |
@@ -186,12 +187,11 @@ static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) | |||
186 | return v; | 187 | return v; |
187 | } | 188 | } |
188 | 189 | ||
189 | static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | 190 | static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) |
190 | { | 191 | { |
191 | u16 power_control; | 192 | u16 power_control; |
192 | u32 reg1; | 193 | u32 reg1; |
193 | int vaux; | 194 | int vaux; |
194 | int ret = 0; | ||
195 | 195 | ||
196 | pr_debug("sky2_set_power_state %d\n", state); | 196 | pr_debug("sky2_set_power_state %d\n", state); |
197 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 197 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
@@ -235,6 +235,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
235 | } | 235 | } |
236 | 236 | ||
237 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | 237 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { |
238 | sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); | ||
238 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | 239 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); |
239 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); | 240 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); |
240 | reg1 &= P_ASPM_CONTROL_MSK; | 241 | reg1 &= P_ASPM_CONTROL_MSK; |
@@ -273,12 +274,10 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
273 | break; | 274 | break; |
274 | default: | 275 | default: |
275 | printk(KERN_ERR PFX "Unknown power state %d\n", state); | 276 | printk(KERN_ERR PFX "Unknown power state %d\n", state); |
276 | ret = -1; | ||
277 | } | 277 | } |
278 | 278 | ||
279 | sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control); | 279 | sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control); |
280 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 280 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
281 | return ret; | ||
282 | } | 281 | } |
283 | 282 | ||
284 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) | 283 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) |
@@ -306,7 +305,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
306 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; | 305 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; |
307 | 306 | ||
308 | if (sky2->autoneg == AUTONEG_ENABLE && | 307 | if (sky2->autoneg == AUTONEG_ENABLE && |
309 | (hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { | 308 | !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { |
310 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 309 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
311 | 310 | ||
312 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | 311 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | |
@@ -977,6 +976,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
977 | struct sky2_hw *hw = sky2->hw; | 976 | struct sky2_hw *hw = sky2->hw; |
978 | unsigned rxq = rxqaddr[sky2->port]; | 977 | unsigned rxq = rxqaddr[sky2->port]; |
979 | int i; | 978 | int i; |
979 | unsigned thresh; | ||
980 | 980 | ||
981 | sky2->rx_put = sky2->rx_next = 0; | 981 | sky2->rx_put = sky2->rx_next = 0; |
982 | sky2_qset(hw, rxq); | 982 | sky2_qset(hw, rxq); |
@@ -1001,9 +1001,21 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
1001 | sky2_rx_add(sky2, re->mapaddr); | 1001 | sky2_rx_add(sky2, re->mapaddr); |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | /* Truncate oversize frames */ | 1004 | |
1005 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8); | 1005 | /* |
1006 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | 1006 | * The receiver hangs if it receives frames larger than the |
1007 | * packet buffer. As a workaround, truncate oversize frames, but | ||
1008 | * the register is limited to 9 bits, so if you do frames > 2052 | ||
1009 | * you better get the MTU right! | ||
1010 | */ | ||
1011 | thresh = (sky2->rx_bufsize - 8) / sizeof(u32); | ||
1012 | if (thresh > 0x1ff) | ||
1013 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); | ||
1014 | else { | ||
1015 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh); | ||
1016 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | ||
1017 | } | ||
1018 | |||
1007 | 1019 | ||
1008 | /* Tell chip about available buffers */ | 1020 | /* Tell chip about available buffers */ |
1009 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 1021 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); |
@@ -1020,7 +1032,25 @@ static int sky2_up(struct net_device *dev) | |||
1020 | struct sky2_hw *hw = sky2->hw; | 1032 | struct sky2_hw *hw = sky2->hw; |
1021 | unsigned port = sky2->port; | 1033 | unsigned port = sky2->port; |
1022 | u32 ramsize, rxspace, imask; | 1034 | u32 ramsize, rxspace, imask; |
1023 | int err = -ENOMEM; | 1035 | int cap, err = -ENOMEM; |
1036 | struct net_device *otherdev = hw->dev[sky2->port^1]; | ||
1037 | |||
1038 | /* | ||
1039 | * On dual port PCI-X card, there is an problem where status | ||
1040 | * can be received out of order due to split transactions | ||
1041 | */ | ||
1042 | if (otherdev && netif_running(otherdev) && | ||
1043 | (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { | ||
1044 | struct sky2_port *osky2 = netdev_priv(otherdev); | ||
1045 | u16 cmd; | ||
1046 | |||
1047 | cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); | ||
1048 | cmd &= ~PCI_X_CMD_MAX_SPLIT; | ||
1049 | sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); | ||
1050 | |||
1051 | sky2->rx_csum = 0; | ||
1052 | osky2->rx_csum = 0; | ||
1053 | } | ||
1024 | 1054 | ||
1025 | if (netif_msg_ifup(sky2)) | 1055 | if (netif_msg_ifup(sky2)) |
1026 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1056 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
@@ -1899,6 +1929,12 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1899 | } | 1929 | } |
1900 | } | 1930 | } |
1901 | 1931 | ||
1932 | /* Is status ring empty or is there more to do? */ | ||
1933 | static inline int sky2_more_work(const struct sky2_hw *hw) | ||
1934 | { | ||
1935 | return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); | ||
1936 | } | ||
1937 | |||
1902 | /* Process status response ring */ | 1938 | /* Process status response ring */ |
1903 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1939 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1904 | { | 1940 | { |
@@ -2125,6 +2161,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2125 | /* If idle then force a fake soft NAPI poll once a second | 2161 | /* If idle then force a fake soft NAPI poll once a second |
2126 | * to work around cases where sharing an edge triggered interrupt. | 2162 | * to work around cases where sharing an edge triggered interrupt. |
2127 | */ | 2163 | */ |
2164 | static inline void sky2_idle_start(struct sky2_hw *hw) | ||
2165 | { | ||
2166 | if (idle_timeout > 0) | ||
2167 | mod_timer(&hw->idle_timer, | ||
2168 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
2169 | } | ||
2170 | |||
2128 | static void sky2_idle(unsigned long arg) | 2171 | static void sky2_idle(unsigned long arg) |
2129 | { | 2172 | { |
2130 | struct sky2_hw *hw = (struct sky2_hw *) arg; | 2173 | struct sky2_hw *hw = (struct sky2_hw *) arg; |
@@ -2144,6 +2187,9 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2144 | int work_done = 0; | 2187 | int work_done = 0; |
2145 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2188 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2146 | 2189 | ||
2190 | if (!~status) | ||
2191 | goto out; | ||
2192 | |||
2147 | if (status & Y2_IS_HW_ERR) | 2193 | if (status & Y2_IS_HW_ERR) |
2148 | sky2_hw_intr(hw); | 2194 | sky2_hw_intr(hw); |
2149 | 2195 | ||
@@ -2171,19 +2217,19 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2171 | if (status & Y2_IS_CHK_TXA2) | 2217 | if (status & Y2_IS_CHK_TXA2) |
2172 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2218 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
2173 | 2219 | ||
2174 | if (status & Y2_IS_STAT_BMU) | ||
2175 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
2176 | |||
2177 | work_done = sky2_status_intr(hw, work_limit); | 2220 | work_done = sky2_status_intr(hw, work_limit); |
2178 | *budget -= work_done; | 2221 | *budget -= work_done; |
2179 | dev0->quota -= work_done; | 2222 | dev0->quota -= work_done; |
2180 | 2223 | ||
2181 | if (work_done >= work_limit) | 2224 | if (status & Y2_IS_STAT_BMU) |
2182 | return 1; | 2225 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2183 | 2226 | ||
2227 | if (sky2_more_work(hw)) | ||
2228 | return 1; | ||
2229 | out: | ||
2184 | netif_rx_complete(dev0); | 2230 | netif_rx_complete(dev0); |
2185 | 2231 | ||
2186 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2232 | sky2_read32(hw, B0_Y2_SP_LISR); |
2187 | return 0; | 2233 | return 0; |
2188 | } | 2234 | } |
2189 | 2235 | ||
@@ -3067,12 +3113,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3067 | sky2->duplex = -1; | 3113 | sky2->duplex = -1; |
3068 | sky2->speed = -1; | 3114 | sky2->speed = -1; |
3069 | sky2->advertising = sky2_supported_modes(hw); | 3115 | sky2->advertising = sky2_supported_modes(hw); |
3070 | 3116 | sky2->rx_csum = 1; | |
3071 | /* Receive checksum disabled for Yukon XL | ||
3072 | * because of observed problems with incorrect | ||
3073 | * values when multiple packets are received in one interrupt | ||
3074 | */ | ||
3075 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | ||
3076 | 3117 | ||
3077 | spin_lock_init(&sky2->phy_lock); | 3118 | spin_lock_init(&sky2->phy_lock); |
3078 | sky2->tx_pending = TX_DEF_PENDING; | 3119 | sky2->tx_pending = TX_DEF_PENDING; |
@@ -3316,9 +3357,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3316 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3357 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3317 | 3358 | ||
3318 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | 3359 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); |
3319 | if (idle_timeout > 0) | 3360 | sky2_idle_start(hw); |
3320 | mod_timer(&hw->idle_timer, | ||
3321 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
3322 | 3361 | ||
3323 | pci_set_drvdata(pdev, hw); | 3362 | pci_set_drvdata(pdev, hw); |
3324 | 3363 | ||
@@ -3391,8 +3430,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3391 | { | 3430 | { |
3392 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 3431 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
3393 | int i; | 3432 | int i; |
3433 | pci_power_t pstate = pci_choose_state(pdev, state); | ||
3434 | |||
3435 | if (!(pstate == PCI_D3hot || pstate == PCI_D3cold)) | ||
3436 | return -EINVAL; | ||
3437 | |||
3438 | del_timer_sync(&hw->idle_timer); | ||
3394 | 3439 | ||
3395 | for (i = 0; i < 2; i++) { | 3440 | for (i = 0; i < hw->ports; i++) { |
3396 | struct net_device *dev = hw->dev[i]; | 3441 | struct net_device *dev = hw->dev[i]; |
3397 | 3442 | ||
3398 | if (dev) { | 3443 | if (dev) { |
@@ -3404,7 +3449,10 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3404 | } | 3449 | } |
3405 | } | 3450 | } |
3406 | 3451 | ||
3407 | return sky2_set_power_state(hw, pci_choose_state(pdev, state)); | 3452 | sky2_write32(hw, B0_IMSK, 0); |
3453 | pci_save_state(pdev); | ||
3454 | sky2_set_power_state(hw, pstate); | ||
3455 | return 0; | ||
3408 | } | 3456 | } |
3409 | 3457 | ||
3410 | static int sky2_resume(struct pci_dev *pdev) | 3458 | static int sky2_resume(struct pci_dev *pdev) |
@@ -3414,15 +3462,15 @@ static int sky2_resume(struct pci_dev *pdev) | |||
3414 | 3462 | ||
3415 | pci_restore_state(pdev); | 3463 | pci_restore_state(pdev); |
3416 | pci_enable_wake(pdev, PCI_D0, 0); | 3464 | pci_enable_wake(pdev, PCI_D0, 0); |
3417 | err = sky2_set_power_state(hw, PCI_D0); | 3465 | sky2_set_power_state(hw, PCI_D0); |
3418 | if (err) | ||
3419 | goto out; | ||
3420 | 3466 | ||
3421 | err = sky2_reset(hw); | 3467 | err = sky2_reset(hw); |
3422 | if (err) | 3468 | if (err) |
3423 | goto out; | 3469 | goto out; |
3424 | 3470 | ||
3425 | for (i = 0; i < 2; i++) { | 3471 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3472 | |||
3473 | for (i = 0; i < hw->ports; i++) { | ||
3426 | struct net_device *dev = hw->dev[i]; | 3474 | struct net_device *dev = hw->dev[i]; |
3427 | if (dev && netif_running(dev)) { | 3475 | if (dev && netif_running(dev)) { |
3428 | netif_device_attach(dev); | 3476 | netif_device_attach(dev); |
@@ -3431,10 +3479,12 @@ static int sky2_resume(struct pci_dev *pdev) | |||
3431 | printk(KERN_ERR PFX "%s: could not up: %d\n", | 3479 | printk(KERN_ERR PFX "%s: could not up: %d\n", |
3432 | dev->name, err); | 3480 | dev->name, err); |
3433 | dev_close(dev); | 3481 | dev_close(dev); |
3434 | break; | 3482 | goto out; |
3435 | } | 3483 | } |
3436 | } | 3484 | } |
3437 | } | 3485 | } |
3486 | |||
3487 | sky2_idle_start(hw); | ||
3438 | out: | 3488 | out: |
3439 | return err; | 3489 | return err; |
3440 | } | 3490 | } |