diff options
Diffstat (limited to 'drivers/net/r6040.c')
-rw-r--r-- | drivers/net/r6040.c | 233 |
1 files changed, 135 insertions, 98 deletions
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 2334f4ebf907..19184e486ae9 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
@@ -61,7 +61,6 @@ | |||
61 | 61 | ||
62 | /* Time in jiffies before concluding the transmitter is hung. */ | 62 | /* Time in jiffies before concluding the transmitter is hung. */ |
63 | #define TX_TIMEOUT (6000 * HZ / 1000) | 63 | #define TX_TIMEOUT (6000 * HZ / 1000) |
64 | #define TIMER_WUT (jiffies + HZ * 1)/* timer wakeup time : 1 second */ | ||
65 | 64 | ||
66 | /* RDC MAC I/O Size */ | 65 | /* RDC MAC I/O Size */ |
67 | #define R6040_IO_SIZE 256 | 66 | #define R6040_IO_SIZE 256 |
@@ -174,8 +173,6 @@ struct r6040_private { | |||
174 | struct net_device *dev; | 173 | struct net_device *dev; |
175 | struct mii_if_info mii_if; | 174 | struct mii_if_info mii_if; |
176 | struct napi_struct napi; | 175 | struct napi_struct napi; |
177 | struct net_device_stats stats; | ||
178 | u16 napi_rx_running; | ||
179 | void __iomem *base; | 176 | void __iomem *base; |
180 | }; | 177 | }; |
181 | 178 | ||
@@ -235,17 +232,53 @@ static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) | |||
235 | phy_write(ioaddr, lp->phy_addr, reg, val); | 232 | phy_write(ioaddr, lp->phy_addr, reg, val); |
236 | } | 233 | } |
237 | 234 | ||
238 | static void r6040_tx_timeout(struct net_device *dev) | 235 | static void r6040_free_txbufs(struct net_device *dev) |
239 | { | 236 | { |
240 | struct r6040_private *priv = netdev_priv(dev); | 237 | struct r6040_private *lp = netdev_priv(dev); |
238 | int i; | ||
241 | 239 | ||
242 | disable_irq(dev->irq); | 240 | for (i = 0; i < TX_DCNT; i++) { |
243 | napi_disable(&priv->napi); | 241 | if (lp->tx_insert_ptr->skb_ptr) { |
244 | spin_lock(&priv->lock); | 242 | pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, |
245 | dev->stats.tx_errors++; | 243 | MAX_BUF_SIZE, PCI_DMA_TODEVICE); |
246 | spin_unlock(&priv->lock); | 244 | dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); |
245 | lp->rx_insert_ptr->skb_ptr = NULL; | ||
246 | } | ||
247 | lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; | ||
248 | } | ||
249 | } | ||
247 | 250 | ||
248 | netif_stop_queue(dev); | 251 | static void r6040_free_rxbufs(struct net_device *dev) |
252 | { | ||
253 | struct r6040_private *lp = netdev_priv(dev); | ||
254 | int i; | ||
255 | |||
256 | for (i = 0; i < RX_DCNT; i++) { | ||
257 | if (lp->rx_insert_ptr->skb_ptr) { | ||
258 | pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, | ||
259 | MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); | ||
260 | dev_kfree_skb(lp->rx_insert_ptr->skb_ptr); | ||
261 | lp->rx_insert_ptr->skb_ptr = NULL; | ||
262 | } | ||
263 | lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, | ||
268 | dma_addr_t desc_dma, int size) | ||
269 | { | ||
270 | struct r6040_descriptor *desc = desc_ring; | ||
271 | dma_addr_t mapping = desc_dma; | ||
272 | |||
273 | while (size-- > 0) { | ||
274 | mapping += sizeof(sizeof(*desc)); | ||
275 | desc->ndesc = cpu_to_le32(mapping); | ||
276 | desc->vndescp = desc + 1; | ||
277 | desc++; | ||
278 | } | ||
279 | desc--; | ||
280 | desc->ndesc = cpu_to_le32(desc_dma); | ||
281 | desc->vndescp = desc_ring; | ||
249 | } | 282 | } |
250 | 283 | ||
251 | /* Allocate skb buffer for rx descriptor */ | 284 | /* Allocate skb buffer for rx descriptor */ |
@@ -256,7 +289,7 @@ static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev) | |||
256 | 289 | ||
257 | descptr = lp->rx_insert_ptr; | 290 | descptr = lp->rx_insert_ptr; |
258 | while (lp->rx_free_desc < RX_DCNT) { | 291 | while (lp->rx_free_desc < RX_DCNT) { |
259 | descptr->skb_ptr = dev_alloc_skb(MAX_BUF_SIZE); | 292 | descptr->skb_ptr = netdev_alloc_skb(dev, MAX_BUF_SIZE); |
260 | 293 | ||
261 | if (!descptr->skb_ptr) | 294 | if (!descptr->skb_ptr) |
262 | break; | 295 | break; |
@@ -272,6 +305,63 @@ static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev) | |||
272 | lp->rx_insert_ptr = descptr; | 305 | lp->rx_insert_ptr = descptr; |
273 | } | 306 | } |
274 | 307 | ||
308 | static void r6040_alloc_txbufs(struct net_device *dev) | ||
309 | { | ||
310 | struct r6040_private *lp = netdev_priv(dev); | ||
311 | void __iomem *ioaddr = lp->base; | ||
312 | |||
313 | lp->tx_free_desc = TX_DCNT; | ||
314 | |||
315 | lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring; | ||
316 | r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT); | ||
317 | |||
318 | iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0); | ||
319 | iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1); | ||
320 | } | ||
321 | |||
322 | static void r6040_alloc_rxbufs(struct net_device *dev) | ||
323 | { | ||
324 | struct r6040_private *lp = netdev_priv(dev); | ||
325 | void __iomem *ioaddr = lp->base; | ||
326 | |||
327 | lp->rx_free_desc = 0; | ||
328 | |||
329 | lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring; | ||
330 | r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT); | ||
331 | |||
332 | rx_buf_alloc(lp, dev); | ||
333 | |||
334 | iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0); | ||
335 | iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1); | ||
336 | } | ||
337 | |||
338 | static void r6040_tx_timeout(struct net_device *dev) | ||
339 | { | ||
340 | struct r6040_private *priv = netdev_priv(dev); | ||
341 | void __iomem *ioaddr = priv->base; | ||
342 | |||
343 | printk(KERN_WARNING "%s: transmit timed out, status %4.4x, PHY status " | ||
344 | "%4.4x\n", | ||
345 | dev->name, ioread16(ioaddr + MIER), | ||
346 | mdio_read(dev, priv->mii_if.phy_id, MII_BMSR)); | ||
347 | |||
348 | disable_irq(dev->irq); | ||
349 | napi_disable(&priv->napi); | ||
350 | spin_lock(&priv->lock); | ||
351 | /* Clear all descriptors */ | ||
352 | r6040_free_txbufs(dev); | ||
353 | r6040_free_rxbufs(dev); | ||
354 | r6040_alloc_txbufs(dev); | ||
355 | r6040_alloc_rxbufs(dev); | ||
356 | |||
357 | /* Reset MAC */ | ||
358 | iowrite16(MAC_RST, ioaddr + MCR1); | ||
359 | spin_unlock(&priv->lock); | ||
360 | enable_irq(dev->irq); | ||
361 | |||
362 | dev->stats.tx_errors++; | ||
363 | netif_wake_queue(dev); | ||
364 | } | ||
275 | 365 | ||
276 | static struct net_device_stats *r6040_get_stats(struct net_device *dev) | 366 | static struct net_device_stats *r6040_get_stats(struct net_device *dev) |
277 | { | 367 | { |
@@ -280,11 +370,11 @@ static struct net_device_stats *r6040_get_stats(struct net_device *dev) | |||
280 | unsigned long flags; | 370 | unsigned long flags; |
281 | 371 | ||
282 | spin_lock_irqsave(&priv->lock, flags); | 372 | spin_lock_irqsave(&priv->lock, flags); |
283 | priv->stats.rx_crc_errors += ioread8(ioaddr + ME_CNT1); | 373 | dev->stats.rx_crc_errors += ioread8(ioaddr + ME_CNT1); |
284 | priv->stats.multicast += ioread8(ioaddr + ME_CNT0); | 374 | dev->stats.multicast += ioread8(ioaddr + ME_CNT0); |
285 | spin_unlock_irqrestore(&priv->lock, flags); | 375 | spin_unlock_irqrestore(&priv->lock, flags); |
286 | 376 | ||
287 | return &priv->stats; | 377 | return &dev->stats; |
288 | } | 378 | } |
289 | 379 | ||
290 | /* Stop RDC MAC and Free the allocated resource */ | 380 | /* Stop RDC MAC and Free the allocated resource */ |
@@ -293,7 +383,6 @@ static void r6040_down(struct net_device *dev) | |||
293 | struct r6040_private *lp = netdev_priv(dev); | 383 | struct r6040_private *lp = netdev_priv(dev); |
294 | void __iomem *ioaddr = lp->base; | 384 | void __iomem *ioaddr = lp->base; |
295 | struct pci_dev *pdev = lp->pdev; | 385 | struct pci_dev *pdev = lp->pdev; |
296 | int i; | ||
297 | int limit = 2048; | 386 | int limit = 2048; |
298 | u16 *adrp; | 387 | u16 *adrp; |
299 | u16 cmd; | 388 | u16 cmd; |
@@ -313,27 +402,12 @@ static void r6040_down(struct net_device *dev) | |||
313 | iowrite16(adrp[1], ioaddr + MID_0M); | 402 | iowrite16(adrp[1], ioaddr + MID_0M); |
314 | iowrite16(adrp[2], ioaddr + MID_0H); | 403 | iowrite16(adrp[2], ioaddr + MID_0H); |
315 | free_irq(dev->irq, dev); | 404 | free_irq(dev->irq, dev); |
405 | |||
316 | /* Free RX buffer */ | 406 | /* Free RX buffer */ |
317 | for (i = 0; i < RX_DCNT; i++) { | 407 | r6040_free_rxbufs(dev); |
318 | if (lp->rx_insert_ptr->skb_ptr) { | ||
319 | pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, | ||
320 | MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); | ||
321 | dev_kfree_skb(lp->rx_insert_ptr->skb_ptr); | ||
322 | lp->rx_insert_ptr->skb_ptr = NULL; | ||
323 | } | ||
324 | lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp; | ||
325 | } | ||
326 | 408 | ||
327 | /* Free TX buffer */ | 409 | /* Free TX buffer */ |
328 | for (i = 0; i < TX_DCNT; i++) { | 410 | r6040_free_txbufs(dev); |
329 | if (lp->tx_insert_ptr->skb_ptr) { | ||
330 | pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, | ||
331 | MAX_BUF_SIZE, PCI_DMA_TODEVICE); | ||
332 | dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); | ||
333 | lp->rx_insert_ptr->skb_ptr = NULL; | ||
334 | } | ||
335 | lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; | ||
336 | } | ||
337 | 411 | ||
338 | /* Free Descriptor memory */ | 412 | /* Free Descriptor memory */ |
339 | pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); | 413 | pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); |
@@ -432,19 +506,24 @@ static int r6040_rx(struct net_device *dev, int limit) | |||
432 | 506 | ||
433 | /* Check for errors */ | 507 | /* Check for errors */ |
434 | err = ioread16(ioaddr + MLSR); | 508 | err = ioread16(ioaddr + MLSR); |
435 | if (err & 0x0400) priv->stats.rx_errors++; | 509 | if (err & 0x0400) |
510 | dev->stats.rx_errors++; | ||
436 | /* RX FIFO over-run */ | 511 | /* RX FIFO over-run */ |
437 | if (err & 0x8000) priv->stats.rx_fifo_errors++; | 512 | if (err & 0x8000) |
513 | dev->stats.rx_fifo_errors++; | ||
438 | /* RX descriptor unavailable */ | 514 | /* RX descriptor unavailable */ |
439 | if (err & 0x0080) priv->stats.rx_frame_errors++; | 515 | if (err & 0x0080) |
516 | dev->stats.rx_frame_errors++; | ||
440 | /* Received packet with length over buffer lenght */ | 517 | /* Received packet with length over buffer lenght */ |
441 | if (err & 0x0020) priv->stats.rx_over_errors++; | 518 | if (err & 0x0020) |
519 | dev->stats.rx_over_errors++; | ||
442 | /* Received packet with too long or short */ | 520 | /* Received packet with too long or short */ |
443 | if (err & (0x0010|0x0008)) priv->stats.rx_length_errors++; | 521 | if (err & (0x0010 | 0x0008)) |
522 | dev->stats.rx_length_errors++; | ||
444 | /* Received packet with CRC errors */ | 523 | /* Received packet with CRC errors */ |
445 | if (err & 0x0004) { | 524 | if (err & 0x0004) { |
446 | spin_lock(&priv->lock); | 525 | spin_lock(&priv->lock); |
447 | priv->stats.rx_crc_errors++; | 526 | dev->stats.rx_crc_errors++; |
448 | spin_unlock(&priv->lock); | 527 | spin_unlock(&priv->lock); |
449 | } | 528 | } |
450 | 529 | ||
@@ -469,8 +548,8 @@ static int r6040_rx(struct net_device *dev, int limit) | |||
469 | /* Send to upper layer */ | 548 | /* Send to upper layer */ |
470 | netif_receive_skb(skb_ptr); | 549 | netif_receive_skb(skb_ptr); |
471 | dev->last_rx = jiffies; | 550 | dev->last_rx = jiffies; |
472 | priv->dev->stats.rx_packets++; | 551 | dev->stats.rx_packets++; |
473 | priv->dev->stats.rx_bytes += descptr->len; | 552 | dev->stats.rx_bytes += descptr->len; |
474 | /* To next descriptor */ | 553 | /* To next descriptor */ |
475 | descptr = descptr->vndescp; | 554 | descptr = descptr->vndescp; |
476 | priv->rx_free_desc--; | 555 | priv->rx_free_desc--; |
@@ -498,11 +577,13 @@ static void r6040_tx(struct net_device *dev) | |||
498 | /* Check for errors */ | 577 | /* Check for errors */ |
499 | err = ioread16(ioaddr + MLSR); | 578 | err = ioread16(ioaddr + MLSR); |
500 | 579 | ||
501 | if (err & 0x0200) priv->stats.rx_fifo_errors++; | 580 | if (err & 0x0200) |
502 | if (err & (0x2000 | 0x4000)) priv->stats.tx_carrier_errors++; | 581 | dev->stats.rx_fifo_errors++; |
582 | if (err & (0x2000 | 0x4000)) | ||
583 | dev->stats.tx_carrier_errors++; | ||
503 | 584 | ||
504 | if (descptr->status & 0x8000) | 585 | if (descptr->status & 0x8000) |
505 | break; /* Not complte */ | 586 | break; /* Not complete */ |
506 | skb_ptr = descptr->skb_ptr; | 587 | skb_ptr = descptr->skb_ptr; |
507 | pci_unmap_single(priv->pdev, descptr->buf, | 588 | pci_unmap_single(priv->pdev, descptr->buf, |
508 | skb_ptr->len, PCI_DMA_TODEVICE); | 589 | skb_ptr->len, PCI_DMA_TODEVICE); |
@@ -545,7 +626,6 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) | |||
545 | struct r6040_private *lp = netdev_priv(dev); | 626 | struct r6040_private *lp = netdev_priv(dev); |
546 | void __iomem *ioaddr = lp->base; | 627 | void __iomem *ioaddr = lp->base; |
547 | u16 status; | 628 | u16 status; |
548 | int handled = 1; | ||
549 | 629 | ||
550 | /* Mask off RDC MAC interrupt */ | 630 | /* Mask off RDC MAC interrupt */ |
551 | iowrite16(MSK_INT, ioaddr + MIER); | 631 | iowrite16(MSK_INT, ioaddr + MIER); |
@@ -565,7 +645,7 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) | |||
565 | if (status & 0x10) | 645 | if (status & 0x10) |
566 | r6040_tx(dev); | 646 | r6040_tx(dev); |
567 | 647 | ||
568 | return IRQ_RETVAL(handled); | 648 | return IRQ_HANDLED; |
569 | } | 649 | } |
570 | 650 | ||
571 | #ifdef CONFIG_NET_POLL_CONTROLLER | 651 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -577,53 +657,15 @@ static void r6040_poll_controller(struct net_device *dev) | |||
577 | } | 657 | } |
578 | #endif | 658 | #endif |
579 | 659 | ||
580 | static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, | ||
581 | dma_addr_t desc_dma, int size) | ||
582 | { | ||
583 | struct r6040_descriptor *desc = desc_ring; | ||
584 | dma_addr_t mapping = desc_dma; | ||
585 | |||
586 | while (size-- > 0) { | ||
587 | mapping += sizeof(sizeof(*desc)); | ||
588 | desc->ndesc = cpu_to_le32(mapping); | ||
589 | desc->vndescp = desc + 1; | ||
590 | desc++; | ||
591 | } | ||
592 | desc--; | ||
593 | desc->ndesc = cpu_to_le32(desc_dma); | ||
594 | desc->vndescp = desc_ring; | ||
595 | } | ||
596 | |||
597 | /* Init RDC MAC */ | 660 | /* Init RDC MAC */ |
598 | static void r6040_up(struct net_device *dev) | 661 | static void r6040_up(struct net_device *dev) |
599 | { | 662 | { |
600 | struct r6040_private *lp = netdev_priv(dev); | 663 | struct r6040_private *lp = netdev_priv(dev); |
601 | void __iomem *ioaddr = lp->base; | 664 | void __iomem *ioaddr = lp->base; |
602 | 665 | ||
603 | /* Initialize */ | 666 | /* Initialise and alloc RX/TX buffers */ |
604 | lp->tx_free_desc = TX_DCNT; | 667 | r6040_alloc_txbufs(dev); |
605 | lp->rx_free_desc = 0; | 668 | r6040_alloc_rxbufs(dev); |
606 | /* Init descriptor */ | ||
607 | lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring; | ||
608 | lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring; | ||
609 | /* Init TX descriptor */ | ||
610 | r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT); | ||
611 | |||
612 | /* Init RX descriptor */ | ||
613 | r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT); | ||
614 | |||
615 | /* Allocate buffer for RX descriptor */ | ||
616 | rx_buf_alloc(lp, dev); | ||
617 | |||
618 | /* | ||
619 | * TX and RX descriptor start registers. | ||
620 | * Lower 16-bits to MxD_SA0. Higher 16-bits to MxD_SA1. | ||
621 | */ | ||
622 | iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0); | ||
623 | iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1); | ||
624 | |||
625 | iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0); | ||
626 | iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1); | ||
627 | 669 | ||
628 | /* Buffer Size Register */ | 670 | /* Buffer Size Register */ |
629 | iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR); | 671 | iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR); |
@@ -689,8 +731,7 @@ static void r6040_timer(unsigned long data) | |||
689 | } | 731 | } |
690 | 732 | ||
691 | /* Timer active again */ | 733 | /* Timer active again */ |
692 | lp->timer.expires = TIMER_WUT; | 734 | mod_timer(&lp->timer, jiffies + round_jiffies(HZ)); |
693 | add_timer(&lp->timer); | ||
694 | } | 735 | } |
695 | 736 | ||
696 | /* Read/set MAC address routines */ | 737 | /* Read/set MAC address routines */ |
@@ -746,14 +787,10 @@ static int r6040_open(struct net_device *dev) | |||
746 | napi_enable(&lp->napi); | 787 | napi_enable(&lp->napi); |
747 | netif_start_queue(dev); | 788 | netif_start_queue(dev); |
748 | 789 | ||
749 | if (lp->switch_sig != ICPLUS_PHY_ID) { | 790 | /* set and active a timer process */ |
750 | /* set and active a timer process */ | 791 | setup_timer(&lp->timer, r6040_timer, (unsigned long) dev); |
751 | init_timer(&lp->timer); | 792 | if (lp->switch_sig != ICPLUS_PHY_ID) |
752 | lp->timer.expires = TIMER_WUT; | 793 | mod_timer(&lp->timer, jiffies + HZ); |
753 | lp->timer.data = (unsigned long)dev; | ||
754 | lp->timer.function = &r6040_timer; | ||
755 | add_timer(&lp->timer); | ||
756 | } | ||
757 | return 0; | 794 | return 0; |
758 | } | 795 | } |
759 | 796 | ||