aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/atl1c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/atl1c')
-rw-r--r--drivers/net/atl1c/atl1c.h6
-rw-r--r--drivers/net/atl1c/atl1c_main.c72
2 files changed, 37 insertions, 41 deletions
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 7e09084f75a9..efe5435bc3d3 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -555,6 +555,9 @@ struct atl1c_adapter {
555#define __AT_TESTING 0x0001 555#define __AT_TESTING 0x0001
556#define __AT_RESETTING 0x0002 556#define __AT_RESETTING 0x0002
557#define __AT_DOWN 0x0003 557#define __AT_DOWN 0x0003
558 u8 work_event;
559#define ATL1C_WORK_EVENT_RESET 0x01
560#define ATL1C_WORK_EVENT_LINK_CHANGE 0x02
558 u32 msg_enable; 561 u32 msg_enable;
559 562
560 bool have_msi; 563 bool have_msi;
@@ -566,8 +569,7 @@ struct atl1c_adapter {
566 spinlock_t tx_lock; 569 spinlock_t tx_lock;
567 atomic_t irq_sem; 570 atomic_t irq_sem;
568 571
569 struct work_struct reset_task; 572 struct work_struct common_task;
570 struct work_struct link_chg_task;
571 struct timer_list watchdog_timer; 573 struct timer_list watchdog_timer;
572 struct timer_list phy_config_timer; 574 struct timer_list phy_config_timer;
573 575
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 1098dad3d381..666261b5851e 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -198,27 +198,12 @@ static void atl1c_phy_config(unsigned long data)
198 198
199void atl1c_reinit_locked(struct atl1c_adapter *adapter) 199void atl1c_reinit_locked(struct atl1c_adapter *adapter)
200{ 200{
201
202 WARN_ON(in_interrupt()); 201 WARN_ON(in_interrupt());
203 atl1c_down(adapter); 202 atl1c_down(adapter);
204 atl1c_up(adapter); 203 atl1c_up(adapter);
205 clear_bit(__AT_RESETTING, &adapter->flags); 204 clear_bit(__AT_RESETTING, &adapter->flags);
206} 205}
207 206
208static void atl1c_reset_task(struct work_struct *work)
209{
210 struct atl1c_adapter *adapter;
211 struct net_device *netdev;
212
213 adapter = container_of(work, struct atl1c_adapter, reset_task);
214 netdev = adapter->netdev;
215
216 netif_device_detach(netdev);
217 atl1c_down(adapter);
218 atl1c_up(adapter);
219 netif_device_attach(netdev);
220}
221
222static void atl1c_check_link_status(struct atl1c_adapter *adapter) 207static void atl1c_check_link_status(struct atl1c_adapter *adapter)
223{ 208{
224 struct atl1c_hw *hw = &adapter->hw; 209 struct atl1c_hw *hw = &adapter->hw;
@@ -275,18 +260,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
275 } 260 }
276} 261}
277 262
278/*
279 * atl1c_link_chg_task - deal with link change event Out of interrupt context
280 * @netdev: network interface device structure
281 */
282static void atl1c_link_chg_task(struct work_struct *work)
283{
284 struct atl1c_adapter *adapter;
285
286 adapter = container_of(work, struct atl1c_adapter, link_chg_task);
287 atl1c_check_link_status(adapter);
288}
289
290static void atl1c_link_chg_event(struct atl1c_adapter *adapter) 263static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
291{ 264{
292 struct net_device *netdev = adapter->netdev; 265 struct net_device *netdev = adapter->netdev;
@@ -311,20 +284,40 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
311 adapter->link_speed = SPEED_0; 284 adapter->link_speed = SPEED_0;
312 } 285 }
313 } 286 }
314 schedule_work(&adapter->link_chg_task); 287
288 adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
289 schedule_work(&adapter->common_task);
315} 290}
316 291
317static void atl1c_del_timer(struct atl1c_adapter *adapter) 292static void atl1c_common_task(struct work_struct *work)
318{ 293{
319 del_timer_sync(&adapter->phy_config_timer); 294 struct atl1c_adapter *adapter;
295 struct net_device *netdev;
296
297 adapter = container_of(work, struct atl1c_adapter, common_task);
298 netdev = adapter->netdev;
299
300 if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
301 netif_device_detach(netdev);
302 atl1c_down(adapter);
303 atl1c_up(adapter);
304 netif_device_attach(netdev);
305 return;
306 }
307
308 if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE)
309 atl1c_check_link_status(adapter);
310
311 return;
320} 312}
321 313
322static void atl1c_cancel_work(struct atl1c_adapter *adapter) 314
315static void atl1c_del_timer(struct atl1c_adapter *adapter)
323{ 316{
324 cancel_work_sync(&adapter->reset_task); 317 del_timer_sync(&adapter->phy_config_timer);
325 cancel_work_sync(&adapter->link_chg_task);
326} 318}
327 319
320
328/* 321/*
329 * atl1c_tx_timeout - Respond to a Tx Hang 322 * atl1c_tx_timeout - Respond to a Tx Hang
330 * @netdev: network interface device structure 323 * @netdev: network interface device structure
@@ -334,7 +327,8 @@ static void atl1c_tx_timeout(struct net_device *netdev)
334 struct atl1c_adapter *adapter = netdev_priv(netdev); 327 struct atl1c_adapter *adapter = netdev_priv(netdev);
335 328
336 /* Do the reset outside of interrupt context */ 329 /* Do the reset outside of interrupt context */
337 schedule_work(&adapter->reset_task); 330 adapter->work_event |= ATL1C_WORK_EVENT_RESET;
331 schedule_work(&adapter->common_task);
338} 332}
339 333
340/* 334/*
@@ -1539,7 +1533,8 @@ static irqreturn_t atl1c_intr(int irq, void *data)
1539 /* reset MAC */ 1533 /* reset MAC */
1540 hw->intr_mask &= ~ISR_ERROR; 1534 hw->intr_mask &= ~ISR_ERROR;
1541 AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); 1535 AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
1542 schedule_work(&adapter->reset_task); 1536 adapter->work_event |= ATL1C_WORK_EVENT_RESET;
1537 schedule_work(&adapter->common_task);
1543 break; 1538 break;
1544 } 1539 }
1545 1540
@@ -2208,8 +2203,7 @@ void atl1c_down(struct atl1c_adapter *adapter)
2208 struct net_device *netdev = adapter->netdev; 2203 struct net_device *netdev = adapter->netdev;
2209 2204
2210 atl1c_del_timer(adapter); 2205 atl1c_del_timer(adapter);
2211 atl1c_cancel_work(adapter); 2206 adapter->work_event = 0; /* clear all event */
2212
2213 /* signal that we're down so the interrupt handler does not 2207 /* signal that we're down so the interrupt handler does not
2214 * reschedule our watchdog timer */ 2208 * reschedule our watchdog timer */
2215 set_bit(__AT_DOWN, &adapter->flags); 2209 set_bit(__AT_DOWN, &adapter->flags);
@@ -2609,8 +2603,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
2609 adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); 2603 adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
2610 2604
2611 atl1c_hw_set_mac_addr(&adapter->hw); 2605 atl1c_hw_set_mac_addr(&adapter->hw);
2612 INIT_WORK(&adapter->reset_task, atl1c_reset_task); 2606 INIT_WORK(&adapter->common_task, atl1c_common_task);
2613 INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task); 2607 adapter->work_event = 0;
2614 err = register_netdev(netdev); 2608 err = register_netdev(netdev);
2615 if (err) { 2609 if (err) {
2616 dev_err(&pdev->dev, "register netdevice failed\n"); 2610 dev_err(&pdev->dev, "register netdevice failed\n");