aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/atl1c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/atl1c')
-rw-r--r--drivers/net/atl1c/atl1c.h17
-rw-r--r--drivers/net/atl1c/atl1c_main.c94
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
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/*
@@ -713,15 +707,21 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
713static inline void atl1c_clean_buffer(struct pci_dev *pdev, 707static 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");