diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 959109609d85..fba1e4d4d83d 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -187,12 +187,11 @@ static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) | |||
187 | return v; | 187 | return v; |
188 | } | 188 | } |
189 | 189 | ||
190 | 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) |
191 | { | 191 | { |
192 | u16 power_control; | 192 | u16 power_control; |
193 | u32 reg1; | 193 | u32 reg1; |
194 | int vaux; | 194 | int vaux; |
195 | int ret = 0; | ||
196 | 195 | ||
197 | pr_debug("sky2_set_power_state %d\n", state); | 196 | pr_debug("sky2_set_power_state %d\n", state); |
198 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 197 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
@@ -275,12 +274,10 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
275 | break; | 274 | break; |
276 | default: | 275 | default: |
277 | printk(KERN_ERR PFX "Unknown power state %d\n", state); | 276 | printk(KERN_ERR PFX "Unknown power state %d\n", state); |
278 | ret = -1; | ||
279 | } | 277 | } |
280 | 278 | ||
281 | 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); |
282 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 280 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
283 | return ret; | ||
284 | } | 281 | } |
285 | 282 | ||
286 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) | 283 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) |
@@ -2164,6 +2161,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2164 | /* 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 |
2165 | * to work around cases where sharing an edge triggered interrupt. | 2162 | * to work around cases where sharing an edge triggered interrupt. |
2166 | */ | 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 | |||
2167 | static void sky2_idle(unsigned long arg) | 2171 | static void sky2_idle(unsigned long arg) |
2168 | { | 2172 | { |
2169 | struct sky2_hw *hw = (struct sky2_hw *) arg; | 2173 | struct sky2_hw *hw = (struct sky2_hw *) arg; |
@@ -2183,6 +2187,9 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2183 | int work_done = 0; | 2187 | int work_done = 0; |
2184 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2188 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2185 | 2189 | ||
2190 | if (!~status) | ||
2191 | goto out; | ||
2192 | |||
2186 | if (status & Y2_IS_HW_ERR) | 2193 | if (status & Y2_IS_HW_ERR) |
2187 | sky2_hw_intr(hw); | 2194 | sky2_hw_intr(hw); |
2188 | 2195 | ||
@@ -2219,7 +2226,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2219 | 2226 | ||
2220 | if (sky2_more_work(hw)) | 2227 | if (sky2_more_work(hw)) |
2221 | return 1; | 2228 | return 1; |
2222 | 2229 | out: | |
2223 | netif_rx_complete(dev0); | 2230 | netif_rx_complete(dev0); |
2224 | 2231 | ||
2225 | sky2_read32(hw, B0_Y2_SP_LISR); | 2232 | sky2_read32(hw, B0_Y2_SP_LISR); |
@@ -2248,8 +2255,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2248 | static void sky2_netpoll(struct net_device *dev) | 2255 | static void sky2_netpoll(struct net_device *dev) |
2249 | { | 2256 | { |
2250 | struct sky2_port *sky2 = netdev_priv(dev); | 2257 | struct sky2_port *sky2 = netdev_priv(dev); |
2258 | struct net_device *dev0 = sky2->hw->dev[0]; | ||
2251 | 2259 | ||
2252 | sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL); | 2260 | if (netif_running(dev) && __netif_rx_schedule_prep(dev0)) |
2261 | __netif_rx_schedule(dev0); | ||
2253 | } | 2262 | } |
2254 | #endif | 2263 | #endif |
2255 | 2264 | ||
@@ -3350,9 +3359,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3350 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3359 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3351 | 3360 | ||
3352 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | 3361 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); |
3353 | if (idle_timeout > 0) | 3362 | sky2_idle_start(hw); |
3354 | mod_timer(&hw->idle_timer, | ||
3355 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
3356 | 3363 | ||
3357 | pci_set_drvdata(pdev, hw); | 3364 | pci_set_drvdata(pdev, hw); |
3358 | 3365 | ||
@@ -3425,8 +3432,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3425 | { | 3432 | { |
3426 | struct sky2_hw *hw = pci_get_drvdata(pdev); | 3433 | struct sky2_hw *hw = pci_get_drvdata(pdev); |
3427 | int i; | 3434 | int i; |
3435 | pci_power_t pstate = pci_choose_state(pdev, state); | ||
3436 | |||
3437 | if (!(pstate == PCI_D3hot || pstate == PCI_D3cold)) | ||
3438 | return -EINVAL; | ||
3439 | |||
3440 | del_timer_sync(&hw->idle_timer); | ||
3428 | 3441 | ||
3429 | for (i = 0; i < 2; i++) { | 3442 | for (i = 0; i < hw->ports; i++) { |
3430 | struct net_device *dev = hw->dev[i]; | 3443 | struct net_device *dev = hw->dev[i]; |
3431 | 3444 | ||
3432 | if (dev) { | 3445 | if (dev) { |
@@ -3435,10 +3448,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3435 | 3448 | ||
3436 | sky2_down(dev); | 3449 | sky2_down(dev); |
3437 | netif_device_detach(dev); | 3450 | netif_device_detach(dev); |
3451 | netif_poll_disable(dev); | ||
3438 | } | 3452 | } |
3439 | } | 3453 | } |
3440 | 3454 | ||
3441 | return sky2_set_power_state(hw, pci_choose_state(pdev, state)); | 3455 | sky2_write32(hw, B0_IMSK, 0); |
3456 | pci_save_state(pdev); | ||
3457 | sky2_set_power_state(hw, pstate); | ||
3458 | return 0; | ||
3442 | } | 3459 | } |
3443 | 3460 | ||
3444 | static int sky2_resume(struct pci_dev *pdev) | 3461 | static int sky2_resume(struct pci_dev *pdev) |
@@ -3448,27 +3465,31 @@ static int sky2_resume(struct pci_dev *pdev) | |||
3448 | 3465 | ||
3449 | pci_restore_state(pdev); | 3466 | pci_restore_state(pdev); |
3450 | pci_enable_wake(pdev, PCI_D0, 0); | 3467 | pci_enable_wake(pdev, PCI_D0, 0); |
3451 | err = sky2_set_power_state(hw, PCI_D0); | 3468 | sky2_set_power_state(hw, PCI_D0); |
3452 | if (err) | ||
3453 | goto out; | ||
3454 | 3469 | ||
3455 | err = sky2_reset(hw); | 3470 | err = sky2_reset(hw); |
3456 | if (err) | 3471 | if (err) |
3457 | goto out; | 3472 | goto out; |
3458 | 3473 | ||
3459 | for (i = 0; i < 2; i++) { | 3474 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3475 | |||
3476 | for (i = 0; i < hw->ports; i++) { | ||
3460 | struct net_device *dev = hw->dev[i]; | 3477 | struct net_device *dev = hw->dev[i]; |
3461 | if (dev && netif_running(dev)) { | 3478 | if (dev && netif_running(dev)) { |
3462 | netif_device_attach(dev); | 3479 | netif_device_attach(dev); |
3480 | netif_poll_enable(dev); | ||
3481 | |||
3463 | err = sky2_up(dev); | 3482 | err = sky2_up(dev); |
3464 | if (err) { | 3483 | if (err) { |
3465 | printk(KERN_ERR PFX "%s: could not up: %d\n", | 3484 | printk(KERN_ERR PFX "%s: could not up: %d\n", |
3466 | dev->name, err); | 3485 | dev->name, err); |
3467 | dev_close(dev); | 3486 | dev_close(dev); |
3468 | break; | 3487 | goto out; |
3469 | } | 3488 | } |
3470 | } | 3489 | } |
3471 | } | 3490 | } |
3491 | |||
3492 | sky2_idle_start(hw); | ||
3472 | out: | 3493 | out: |
3473 | return err; | 3494 | return err; |
3474 | } | 3495 | } |