diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2011-10-05 03:24:41 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-10-07 01:38:25 -0400 |
commit | a4010afef585b7142eb605e3a6e4210c0e1b2957 (patch) | |
tree | 770fa2d71222702cae44fd730582b8937b958f43 /drivers/net/ethernet/intel | |
parent | 19d478bbe690a37489f58843dec20a456573d89f (diff) |
e1000: convert hardware management from timers to threads
Thomas Gleixner (tglx) reported that e1000 was delaying for many milliseconds
(using mdelay) from inside timer/interrupt context. None of these paths are
performance critical and can be moved into threads/work items. This patch
implements the work items and the next patch changes the mdelays to msleeps.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Tushar Dave <tushar.n.dave@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000.h | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_main.c | 129 |
2 files changed, 55 insertions, 84 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h index 4ea87b19ac1a..fc6fbbda98d9 100644 --- a/drivers/net/ethernet/intel/e1000/e1000.h +++ b/drivers/net/ethernet/intel/e1000/e1000.h | |||
@@ -214,9 +214,6 @@ struct e1000_rx_ring { | |||
214 | /* board specific private data structure */ | 214 | /* board specific private data structure */ |
215 | 215 | ||
216 | struct e1000_adapter { | 216 | struct e1000_adapter { |
217 | struct timer_list tx_fifo_stall_timer; | ||
218 | struct timer_list watchdog_timer; | ||
219 | struct timer_list phy_info_timer; | ||
220 | unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; | 217 | unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; |
221 | u16 mng_vlan_id; | 218 | u16 mng_vlan_id; |
222 | u32 bd_number; | 219 | u32 bd_number; |
@@ -237,7 +234,6 @@ struct e1000_adapter { | |||
237 | u16 tx_itr; | 234 | u16 tx_itr; |
238 | u16 rx_itr; | 235 | u16 rx_itr; |
239 | 236 | ||
240 | struct work_struct reset_task; | ||
241 | u8 fc_autoneg; | 237 | u8 fc_autoneg; |
242 | 238 | ||
243 | /* TX */ | 239 | /* TX */ |
@@ -310,8 +306,10 @@ struct e1000_adapter { | |||
310 | 306 | ||
311 | bool discarding; | 307 | bool discarding; |
312 | 308 | ||
313 | struct work_struct fifo_stall_task; | 309 | struct work_struct reset_task; |
314 | struct work_struct phy_info_task; | 310 | struct delayed_work watchdog_task; |
311 | struct delayed_work fifo_stall_task; | ||
312 | struct delayed_work phy_info_task; | ||
315 | }; | 313 | }; |
316 | 314 | ||
317 | enum e1000_state_t { | 315 | enum e1000_state_t { |
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 4bbc05ad9ba1..a0c5ea0d3fd5 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c | |||
@@ -131,10 +131,8 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter, | |||
131 | static void e1000_clean_rx_ring(struct e1000_adapter *adapter, | 131 | static void e1000_clean_rx_ring(struct e1000_adapter *adapter, |
132 | struct e1000_rx_ring *rx_ring); | 132 | struct e1000_rx_ring *rx_ring); |
133 | static void e1000_set_rx_mode(struct net_device *netdev); | 133 | static void e1000_set_rx_mode(struct net_device *netdev); |
134 | static void e1000_update_phy_info(unsigned long data); | ||
135 | static void e1000_update_phy_info_task(struct work_struct *work); | 134 | static void e1000_update_phy_info_task(struct work_struct *work); |
136 | static void e1000_watchdog(unsigned long data); | 135 | static void e1000_watchdog(struct work_struct *work); |
137 | static void e1000_82547_tx_fifo_stall(unsigned long data); | ||
138 | static void e1000_82547_tx_fifo_stall_task(struct work_struct *work); | 136 | static void e1000_82547_tx_fifo_stall_task(struct work_struct *work); |
139 | static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, | 137 | static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, |
140 | struct net_device *netdev); | 138 | struct net_device *netdev); |
@@ -493,6 +491,15 @@ out: | |||
493 | return; | 491 | return; |
494 | } | 492 | } |
495 | 493 | ||
494 | static void e1000_down_and_stop(struct e1000_adapter *adapter) | ||
495 | { | ||
496 | set_bit(__E1000_DOWN, &adapter->flags); | ||
497 | cancel_work_sync(&adapter->reset_task); | ||
498 | cancel_delayed_work_sync(&adapter->watchdog_task); | ||
499 | cancel_delayed_work_sync(&adapter->phy_info_task); | ||
500 | cancel_delayed_work_sync(&adapter->fifo_stall_task); | ||
501 | } | ||
502 | |||
496 | void e1000_down(struct e1000_adapter *adapter) | 503 | void e1000_down(struct e1000_adapter *adapter) |
497 | { | 504 | { |
498 | struct e1000_hw *hw = &adapter->hw; | 505 | struct e1000_hw *hw = &adapter->hw; |
@@ -522,13 +529,9 @@ void e1000_down(struct e1000_adapter *adapter) | |||
522 | /* | 529 | /* |
523 | * Setting DOWN must be after irq_disable to prevent | 530 | * Setting DOWN must be after irq_disable to prevent |
524 | * a screaming interrupt. Setting DOWN also prevents | 531 | * a screaming interrupt. Setting DOWN also prevents |
525 | * timers and tasks from rescheduling. | 532 | * tasks from rescheduling. |
526 | */ | 533 | */ |
527 | set_bit(__E1000_DOWN, &adapter->flags); | 534 | e1000_down_and_stop(adapter); |
528 | |||
529 | del_timer_sync(&adapter->tx_fifo_stall_timer); | ||
530 | del_timer_sync(&adapter->watchdog_timer); | ||
531 | del_timer_sync(&adapter->phy_info_timer); | ||
532 | 535 | ||
533 | adapter->link_speed = 0; | 536 | adapter->link_speed = 0; |
534 | adapter->link_duplex = 0; | 537 | adapter->link_duplex = 0; |
@@ -1120,21 +1123,12 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
1120 | if (!is_valid_ether_addr(netdev->perm_addr)) | 1123 | if (!is_valid_ether_addr(netdev->perm_addr)) |
1121 | e_err(probe, "Invalid MAC Address\n"); | 1124 | e_err(probe, "Invalid MAC Address\n"); |
1122 | 1125 | ||
1123 | init_timer(&adapter->tx_fifo_stall_timer); | ||
1124 | adapter->tx_fifo_stall_timer.function = e1000_82547_tx_fifo_stall; | ||
1125 | adapter->tx_fifo_stall_timer.data = (unsigned long)adapter; | ||
1126 | |||
1127 | init_timer(&adapter->watchdog_timer); | ||
1128 | adapter->watchdog_timer.function = e1000_watchdog; | ||
1129 | adapter->watchdog_timer.data = (unsigned long) adapter; | ||
1130 | |||
1131 | init_timer(&adapter->phy_info_timer); | ||
1132 | adapter->phy_info_timer.function = e1000_update_phy_info; | ||
1133 | adapter->phy_info_timer.data = (unsigned long)adapter; | ||
1134 | 1126 | ||
1135 | INIT_WORK(&adapter->fifo_stall_task, e1000_82547_tx_fifo_stall_task); | 1127 | INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog); |
1128 | INIT_DELAYED_WORK(&adapter->fifo_stall_task, | ||
1129 | e1000_82547_tx_fifo_stall_task); | ||
1130 | INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task); | ||
1136 | INIT_WORK(&adapter->reset_task, e1000_reset_task); | 1131 | INIT_WORK(&adapter->reset_task, e1000_reset_task); |
1137 | INIT_WORK(&adapter->phy_info_task, e1000_update_phy_info_task); | ||
1138 | 1132 | ||
1139 | e1000_check_options(adapter); | 1133 | e1000_check_options(adapter); |
1140 | 1134 | ||
@@ -1279,13 +1273,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) | |||
1279 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1273 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1280 | struct e1000_hw *hw = &adapter->hw; | 1274 | struct e1000_hw *hw = &adapter->hw; |
1281 | 1275 | ||
1282 | set_bit(__E1000_DOWN, &adapter->flags); | 1276 | e1000_down_and_stop(adapter); |
1283 | del_timer_sync(&adapter->tx_fifo_stall_timer); | ||
1284 | del_timer_sync(&adapter->watchdog_timer); | ||
1285 | del_timer_sync(&adapter->phy_info_timer); | ||
1286 | |||
1287 | cancel_work_sync(&adapter->reset_task); | ||
1288 | |||
1289 | e1000_release_manageability(adapter); | 1277 | e1000_release_manageability(adapter); |
1290 | 1278 | ||
1291 | unregister_netdev(netdev); | 1279 | unregister_netdev(netdev); |
@@ -1369,7 +1357,7 @@ static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter) | |||
1369 | * The open entry point is called when a network interface is made | 1357 | * The open entry point is called when a network interface is made |
1370 | * active by the system (IFF_UP). At this point all resources needed | 1358 | * active by the system (IFF_UP). At this point all resources needed |
1371 | * for transmit and receive operations are allocated, the interrupt | 1359 | * for transmit and receive operations are allocated, the interrupt |
1372 | * handler is registered with the OS, the watchdog timer is started, | 1360 | * handler is registered with the OS, the watchdog task is started, |
1373 | * and the stack is notified that the interface is ready. | 1361 | * and the stack is notified that the interface is ready. |
1374 | **/ | 1362 | **/ |
1375 | 1363 | ||
@@ -2331,46 +2319,32 @@ static void e1000_set_rx_mode(struct net_device *netdev) | |||
2331 | kfree(mcarray); | 2319 | kfree(mcarray); |
2332 | } | 2320 | } |
2333 | 2321 | ||
2334 | /* Need to wait a few seconds after link up to get diagnostic information from | 2322 | /** |
2335 | * the phy */ | 2323 | * e1000_update_phy_info_task - get phy info |
2336 | 2324 | * @work: work struct contained inside adapter struct | |
2337 | static void e1000_update_phy_info(unsigned long data) | 2325 | * |
2338 | { | 2326 | * Need to wait a few seconds after link up to get diagnostic information from |
2339 | struct e1000_adapter *adapter = (struct e1000_adapter *)data; | 2327 | * the phy |
2340 | schedule_work(&adapter->phy_info_task); | 2328 | */ |
2341 | } | ||
2342 | |||
2343 | static void e1000_update_phy_info_task(struct work_struct *work) | 2329 | static void e1000_update_phy_info_task(struct work_struct *work) |
2344 | { | 2330 | { |
2345 | struct e1000_adapter *adapter = container_of(work, | 2331 | struct e1000_adapter *adapter = container_of(work, |
2346 | struct e1000_adapter, | 2332 | struct e1000_adapter, |
2347 | phy_info_task); | 2333 | phy_info_task.work); |
2348 | struct e1000_hw *hw = &adapter->hw; | ||
2349 | |||
2350 | rtnl_lock(); | 2334 | rtnl_lock(); |
2351 | e1000_phy_get_info(hw, &adapter->phy_info); | 2335 | e1000_phy_get_info(&adapter->hw, &adapter->phy_info); |
2352 | rtnl_unlock(); | 2336 | rtnl_unlock(); |
2353 | } | 2337 | } |
2354 | 2338 | ||
2355 | /** | 2339 | /** |
2356 | * e1000_82547_tx_fifo_stall - Timer Call-back | ||
2357 | * @data: pointer to adapter cast into an unsigned long | ||
2358 | **/ | ||
2359 | static void e1000_82547_tx_fifo_stall(unsigned long data) | ||
2360 | { | ||
2361 | struct e1000_adapter *adapter = (struct e1000_adapter *)data; | ||
2362 | schedule_work(&adapter->fifo_stall_task); | ||
2363 | } | ||
2364 | |||
2365 | /** | ||
2366 | * e1000_82547_tx_fifo_stall_task - task to complete work | 2340 | * e1000_82547_tx_fifo_stall_task - task to complete work |
2367 | * @work: work struct contained inside adapter struct | 2341 | * @work: work struct contained inside adapter struct |
2368 | **/ | 2342 | **/ |
2369 | static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) | 2343 | static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) |
2370 | { | 2344 | { |
2371 | struct e1000_adapter *adapter = container_of(work, | 2345 | struct e1000_adapter *adapter = container_of(work, |
2372 | struct e1000_adapter, | 2346 | struct e1000_adapter, |
2373 | fifo_stall_task); | 2347 | fifo_stall_task.work); |
2374 | struct e1000_hw *hw = &adapter->hw; | 2348 | struct e1000_hw *hw = &adapter->hw; |
2375 | struct net_device *netdev = adapter->netdev; | 2349 | struct net_device *netdev = adapter->netdev; |
2376 | u32 tctl; | 2350 | u32 tctl; |
@@ -2393,7 +2367,7 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) | |||
2393 | atomic_set(&adapter->tx_fifo_stall, 0); | 2367 | atomic_set(&adapter->tx_fifo_stall, 0); |
2394 | netif_wake_queue(netdev); | 2368 | netif_wake_queue(netdev); |
2395 | } else if (!test_bit(__E1000_DOWN, &adapter->flags)) { | 2369 | } else if (!test_bit(__E1000_DOWN, &adapter->flags)) { |
2396 | mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); | 2370 | schedule_delayed_work(&adapter->fifo_stall_task, 1); |
2397 | } | 2371 | } |
2398 | } | 2372 | } |
2399 | rtnl_unlock(); | 2373 | rtnl_unlock(); |
@@ -2437,12 +2411,14 @@ bool e1000_has_link(struct e1000_adapter *adapter) | |||
2437 | } | 2411 | } |
2438 | 2412 | ||
2439 | /** | 2413 | /** |
2440 | * e1000_watchdog - Timer Call-back | 2414 | * e1000_watchdog - work function |
2441 | * @data: pointer to adapter cast into an unsigned long | 2415 | * @work: work struct contained inside adapter struct |
2442 | **/ | 2416 | **/ |
2443 | static void e1000_watchdog(unsigned long data) | 2417 | static void e1000_watchdog(struct work_struct *work) |
2444 | { | 2418 | { |
2445 | struct e1000_adapter *adapter = (struct e1000_adapter *)data; | 2419 | struct e1000_adapter *adapter = container_of(work, |
2420 | struct e1000_adapter, | ||
2421 | watchdog_task.work); | ||
2446 | struct e1000_hw *hw = &adapter->hw; | 2422 | struct e1000_hw *hw = &adapter->hw; |
2447 | struct net_device *netdev = adapter->netdev; | 2423 | struct net_device *netdev = adapter->netdev; |
2448 | struct e1000_tx_ring *txdr = adapter->tx_ring; | 2424 | struct e1000_tx_ring *txdr = adapter->tx_ring; |
@@ -2493,8 +2469,8 @@ static void e1000_watchdog(unsigned long data) | |||
2493 | 2469 | ||
2494 | netif_carrier_on(netdev); | 2470 | netif_carrier_on(netdev); |
2495 | if (!test_bit(__E1000_DOWN, &adapter->flags)) | 2471 | if (!test_bit(__E1000_DOWN, &adapter->flags)) |
2496 | mod_timer(&adapter->phy_info_timer, | 2472 | schedule_delayed_work(&adapter->phy_info_task, |
2497 | round_jiffies(jiffies + 2 * HZ)); | 2473 | 2 * HZ); |
2498 | adapter->smartspeed = 0; | 2474 | adapter->smartspeed = 0; |
2499 | } | 2475 | } |
2500 | } else { | 2476 | } else { |
@@ -2506,8 +2482,8 @@ static void e1000_watchdog(unsigned long data) | |||
2506 | netif_carrier_off(netdev); | 2482 | netif_carrier_off(netdev); |
2507 | 2483 | ||
2508 | if (!test_bit(__E1000_DOWN, &adapter->flags)) | 2484 | if (!test_bit(__E1000_DOWN, &adapter->flags)) |
2509 | mod_timer(&adapter->phy_info_timer, | 2485 | schedule_delayed_work(&adapter->phy_info_task, |
2510 | round_jiffies(jiffies + 2 * HZ)); | 2486 | 2 * HZ); |
2511 | } | 2487 | } |
2512 | 2488 | ||
2513 | e1000_smartspeed(adapter); | 2489 | e1000_smartspeed(adapter); |
@@ -2563,10 +2539,9 @@ link_up: | |||
2563 | /* Force detection of hung controller every watchdog period */ | 2539 | /* Force detection of hung controller every watchdog period */ |
2564 | adapter->detect_tx_hung = true; | 2540 | adapter->detect_tx_hung = true; |
2565 | 2541 | ||
2566 | /* Reset the timer */ | 2542 | /* Reschedule the task */ |
2567 | if (!test_bit(__E1000_DOWN, &adapter->flags)) | 2543 | if (!test_bit(__E1000_DOWN, &adapter->flags)) |
2568 | mod_timer(&adapter->watchdog_timer, | 2544 | schedule_delayed_work(&adapter->watchdog_task, 2 * HZ); |
2569 | round_jiffies(jiffies + 2 * HZ)); | ||
2570 | } | 2545 | } |
2571 | 2546 | ||
2572 | enum latency_range { | 2547 | enum latency_range { |
@@ -3206,14 +3181,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, | |||
3206 | if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) | 3181 | if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) |
3207 | return NETDEV_TX_BUSY; | 3182 | return NETDEV_TX_BUSY; |
3208 | 3183 | ||
3209 | if (unlikely(hw->mac_type == e1000_82547)) { | 3184 | if (unlikely((hw->mac_type == e1000_82547) && |
3210 | if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) { | 3185 | (e1000_82547_fifo_workaround(adapter, skb)))) { |
3211 | netif_stop_queue(netdev); | 3186 | netif_stop_queue(netdev); |
3212 | if (!test_bit(__E1000_DOWN, &adapter->flags)) | 3187 | if (!test_bit(__E1000_DOWN, &adapter->flags)) |
3213 | mod_timer(&adapter->tx_fifo_stall_timer, | 3188 | schedule_delayed_work(&adapter->fifo_stall_task, 1); |
3214 | jiffies + 1); | 3189 | return NETDEV_TX_BUSY; |
3215 | return NETDEV_TX_BUSY; | ||
3216 | } | ||
3217 | } | 3190 | } |
3218 | 3191 | ||
3219 | if (vlan_tx_tag_present(skb)) { | 3192 | if (vlan_tx_tag_present(skb)) { |
@@ -3283,7 +3256,7 @@ static void e1000_reset_task(struct work_struct *work) | |||
3283 | * @netdev: network interface device structure | 3256 | * @netdev: network interface device structure |
3284 | * | 3257 | * |
3285 | * Returns the address of the device statistics structure. | 3258 | * Returns the address of the device statistics structure. |
3286 | * The statistics are actually updated from the timer callback. | 3259 | * The statistics are actually updated from the watchdog. |
3287 | **/ | 3260 | **/ |
3288 | 3261 | ||
3289 | static struct net_device_stats *e1000_get_stats(struct net_device *netdev) | 3262 | static struct net_device_stats *e1000_get_stats(struct net_device *netdev) |
@@ -3551,7 +3524,7 @@ static irqreturn_t e1000_intr(int irq, void *data) | |||
3551 | hw->get_link_status = 1; | 3524 | hw->get_link_status = 1; |
3552 | /* guard against interrupt when we're going down */ | 3525 | /* guard against interrupt when we're going down */ |
3553 | if (!test_bit(__E1000_DOWN, &adapter->flags)) | 3526 | if (!test_bit(__E1000_DOWN, &adapter->flags)) |
3554 | mod_timer(&adapter->watchdog_timer, jiffies + 1); | 3527 | schedule_delayed_work(&adapter->watchdog_task, 1); |
3555 | } | 3528 | } |
3556 | 3529 | ||
3557 | /* disable interrupts, without the synchronize_irq bit */ | 3530 | /* disable interrupts, without the synchronize_irq bit */ |