diff options
Diffstat (limited to 'drivers/net/atl1c')
-rw-r--r-- | drivers/net/atl1c/atl1c.h | 17 | ||||
-rw-r--r-- | drivers/net/atl1c/atl1c_main.c | 94 |
2 files changed, 61 insertions, 50 deletions
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index a348a22551d9..efe5435bc3d3 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h | |||
@@ -479,6 +479,9 @@ struct atl1c_buffer { | |||
479 | #define ATL1C_PCIMAP_PAGE 0x0008 | 479 | #define ATL1C_PCIMAP_PAGE 0x0008 |
480 | #define ATL1C_PCIMAP_TYPE_MASK 0x000C | 480 | #define ATL1C_PCIMAP_TYPE_MASK 0x000C |
481 | 481 | ||
482 | #define ATL1C_PCIMAP_TODEVICE 0x0010 | ||
483 | #define ATL1C_PCIMAP_FROMDEVICE 0x0020 | ||
484 | #define ATL1C_PCIMAP_DIRECTION_MASK 0x0030 | ||
482 | dma_addr_t dma; | 485 | dma_addr_t dma; |
483 | }; | 486 | }; |
484 | 487 | ||
@@ -487,9 +490,11 @@ struct atl1c_buffer { | |||
487 | ((buff)->flags) |= (state); \ | 490 | ((buff)->flags) |= (state); \ |
488 | } while (0) | 491 | } while (0) |
489 | 492 | ||
490 | #define ATL1C_SET_PCIMAP_TYPE(buff, type) do { \ | 493 | #define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do { \ |
491 | ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ | 494 | ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ |
492 | ((buff)->flags) |= (type); \ | 495 | ((buff)->flags) |= (type); \ |
496 | ((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK; \ | ||
497 | ((buff)->flags) |= (direction); \ | ||
493 | } while (0) | 498 | } while (0) |
494 | 499 | ||
495 | /* transimit packet descriptor (tpd) ring */ | 500 | /* transimit packet descriptor (tpd) ring */ |
@@ -550,6 +555,9 @@ struct atl1c_adapter { | |||
550 | #define __AT_TESTING 0x0001 | 555 | #define __AT_TESTING 0x0001 |
551 | #define __AT_RESETTING 0x0002 | 556 | #define __AT_RESETTING 0x0002 |
552 | #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 | ||
553 | u32 msg_enable; | 561 | u32 msg_enable; |
554 | 562 | ||
555 | bool have_msi; | 563 | bool have_msi; |
@@ -561,8 +569,7 @@ struct atl1c_adapter { | |||
561 | spinlock_t tx_lock; | 569 | spinlock_t tx_lock; |
562 | atomic_t irq_sem; | 570 | atomic_t irq_sem; |
563 | 571 | ||
564 | struct work_struct reset_task; | 572 | struct work_struct common_task; |
565 | struct work_struct link_chg_task; | ||
566 | struct timer_list watchdog_timer; | 573 | struct timer_list watchdog_timer; |
567 | struct timer_list phy_config_timer; | 574 | struct timer_list phy_config_timer; |
568 | 575 | ||
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 1e2f57d4c367..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 | ||
199 | void atl1c_reinit_locked(struct atl1c_adapter *adapter) | 199 | void 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 | ||
208 | static 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 | |||
222 | static void atl1c_check_link_status(struct atl1c_adapter *adapter) | 207 | static 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 | */ | ||
282 | static 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 | |||
290 | static void atl1c_link_chg_event(struct atl1c_adapter *adapter) | 263 | static 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 | ||
317 | static void atl1c_del_timer(struct atl1c_adapter *adapter) | 292 | static 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 | ||
322 | static void atl1c_cancel_work(struct atl1c_adapter *adapter) | 314 | |
315 | static 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 | /* |
@@ -713,15 +707,21 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter) | |||
713 | static inline void atl1c_clean_buffer(struct pci_dev *pdev, | 707 | static inline void atl1c_clean_buffer(struct pci_dev *pdev, |
714 | struct atl1c_buffer *buffer_info, int in_irq) | 708 | struct atl1c_buffer *buffer_info, int in_irq) |
715 | { | 709 | { |
710 | u16 pci_driection; | ||
716 | if (buffer_info->flags & ATL1C_BUFFER_FREE) | 711 | if (buffer_info->flags & ATL1C_BUFFER_FREE) |
717 | return; | 712 | return; |
718 | if (buffer_info->dma) { | 713 | if (buffer_info->dma) { |
714 | if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE) | ||
715 | pci_driection = PCI_DMA_FROMDEVICE; | ||
716 | else | ||
717 | pci_driection = PCI_DMA_TODEVICE; | ||
718 | |||
719 | if (buffer_info->flags & ATL1C_PCIMAP_SINGLE) | 719 | if (buffer_info->flags & ATL1C_PCIMAP_SINGLE) |
720 | pci_unmap_single(pdev, buffer_info->dma, | 720 | pci_unmap_single(pdev, buffer_info->dma, |
721 | buffer_info->length, PCI_DMA_TODEVICE); | 721 | buffer_info->length, pci_driection); |
722 | else if (buffer_info->flags & ATL1C_PCIMAP_PAGE) | 722 | else if (buffer_info->flags & ATL1C_PCIMAP_PAGE) |
723 | pci_unmap_page(pdev, buffer_info->dma, | 723 | pci_unmap_page(pdev, buffer_info->dma, |
724 | buffer_info->length, PCI_DMA_TODEVICE); | 724 | buffer_info->length, pci_driection); |
725 | } | 725 | } |
726 | if (buffer_info->skb) { | 726 | if (buffer_info->skb) { |
727 | if (in_irq) | 727 | if (in_irq) |
@@ -1533,7 +1533,8 @@ static irqreturn_t atl1c_intr(int irq, void *data) | |||
1533 | /* reset MAC */ | 1533 | /* reset MAC */ |
1534 | hw->intr_mask &= ~ISR_ERROR; | 1534 | hw->intr_mask &= ~ISR_ERROR; |
1535 | AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); | 1535 | AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); |
1536 | schedule_work(&adapter->reset_task); | 1536 | adapter->work_event |= ATL1C_WORK_EVENT_RESET; |
1537 | schedule_work(&adapter->common_task); | ||
1537 | break; | 1538 | break; |
1538 | } | 1539 | } |
1539 | 1540 | ||
@@ -1606,7 +1607,8 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid | |||
1606 | buffer_info->dma = pci_map_single(pdev, vir_addr, | 1607 | buffer_info->dma = pci_map_single(pdev, vir_addr, |
1607 | buffer_info->length, | 1608 | buffer_info->length, |
1608 | PCI_DMA_FROMDEVICE); | 1609 | PCI_DMA_FROMDEVICE); |
1609 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); | 1610 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, |
1611 | ATL1C_PCIMAP_FROMDEVICE); | ||
1610 | rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); | 1612 | rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); |
1611 | rfd_next_to_use = next_next; | 1613 | rfd_next_to_use = next_next; |
1612 | if (++next_next == rfd_ring->count) | 1614 | if (++next_next == rfd_ring->count) |
@@ -1967,7 +1969,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
1967 | buffer_info->dma = pci_map_single(adapter->pdev, | 1969 | buffer_info->dma = pci_map_single(adapter->pdev, |
1968 | skb->data, hdr_len, PCI_DMA_TODEVICE); | 1970 | skb->data, hdr_len, PCI_DMA_TODEVICE); |
1969 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 1971 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); |
1970 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); | 1972 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, |
1973 | ATL1C_PCIMAP_TODEVICE); | ||
1971 | mapped_len += map_len; | 1974 | mapped_len += map_len; |
1972 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); | 1975 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); |
1973 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); | 1976 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); |
@@ -1988,7 +1991,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
1988 | pci_map_single(adapter->pdev, skb->data + mapped_len, | 1991 | pci_map_single(adapter->pdev, skb->data + mapped_len, |
1989 | buffer_info->length, PCI_DMA_TODEVICE); | 1992 | buffer_info->length, PCI_DMA_TODEVICE); |
1990 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 1993 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); |
1991 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE); | 1994 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, |
1995 | ATL1C_PCIMAP_TODEVICE); | ||
1992 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); | 1996 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); |
1993 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); | 1997 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); |
1994 | } | 1998 | } |
@@ -2009,7 +2013,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
2009 | buffer_info->length, | 2013 | buffer_info->length, |
2010 | PCI_DMA_TODEVICE); | 2014 | PCI_DMA_TODEVICE); |
2011 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 2015 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); |
2012 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE); | 2016 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, |
2017 | ATL1C_PCIMAP_TODEVICE); | ||
2013 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); | 2018 | use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); |
2014 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); | 2019 | use_tpd->buffer_len = cpu_to_le16(buffer_info->length); |
2015 | } | 2020 | } |
@@ -2198,8 +2203,7 @@ void atl1c_down(struct atl1c_adapter *adapter) | |||
2198 | struct net_device *netdev = adapter->netdev; | 2203 | struct net_device *netdev = adapter->netdev; |
2199 | 2204 | ||
2200 | atl1c_del_timer(adapter); | 2205 | atl1c_del_timer(adapter); |
2201 | atl1c_cancel_work(adapter); | 2206 | adapter->work_event = 0; /* clear all event */ |
2202 | |||
2203 | /* signal that we're down so the interrupt handler does not | 2207 | /* signal that we're down so the interrupt handler does not |
2204 | * reschedule our watchdog timer */ | 2208 | * reschedule our watchdog timer */ |
2205 | set_bit(__AT_DOWN, &adapter->flags); | 2209 | set_bit(__AT_DOWN, &adapter->flags); |
@@ -2599,8 +2603,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, | |||
2599 | adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); | 2603 | adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); |
2600 | 2604 | ||
2601 | atl1c_hw_set_mac_addr(&adapter->hw); | 2605 | atl1c_hw_set_mac_addr(&adapter->hw); |
2602 | INIT_WORK(&adapter->reset_task, atl1c_reset_task); | 2606 | INIT_WORK(&adapter->common_task, atl1c_common_task); |
2603 | INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task); | 2607 | adapter->work_event = 0; |
2604 | err = register_netdev(netdev); | 2608 | err = register_netdev(netdev); |
2605 | if (err) { | 2609 | if (err) { |
2606 | dev_err(&pdev->dev, "register netdevice failed\n"); | 2610 | dev_err(&pdev->dev, "register netdevice failed\n"); |