aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ibm_newemac/mal.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 10c267b2b961..1839d3f154a3 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -28,6 +28,7 @@
28#include <linux/delay.h> 28#include <linux/delay.h>
29 29
30#include "core.h" 30#include "core.h"
31#include <asm/dcr-regs.h>
31 32
32static int mal_count; 33static int mal_count;
33 34
@@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
279 mal_schedule_poll(mal); 280 mal_schedule_poll(mal);
280 set_mal_dcrn(mal, MAL_TXEOBISR, r); 281 set_mal_dcrn(mal, MAL_TXEOBISR, r);
281 282
283 if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
284 mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
285 (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
286
282 return IRQ_HANDLED; 287 return IRQ_HANDLED;
283} 288}
284 289
@@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
293 mal_schedule_poll(mal); 298 mal_schedule_poll(mal);
294 set_mal_dcrn(mal, MAL_RXEOBISR, r); 299 set_mal_dcrn(mal, MAL_RXEOBISR, r);
295 300
301 if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
302 mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
303 (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
304
296 return IRQ_HANDLED; 305 return IRQ_HANDLED;
297} 306}
298 307
@@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
336 return IRQ_HANDLED; 345 return IRQ_HANDLED;
337} 346}
338 347
348static irqreturn_t mal_int(int irq, void *dev_instance)
349{
350 struct mal_instance *mal = dev_instance;
351 u32 esr = get_mal_dcrn(mal, MAL_ESR);
352
353 if (esr & MAL_ESR_EVB) {
354 /* descriptor error */
355 if (esr & MAL_ESR_DE) {
356 if (esr & MAL_ESR_CIDT)
357 return mal_rxde(irq, dev_instance);
358 else
359 return mal_txde(irq, dev_instance);
360 } else { /* SERR */
361 return mal_serr(irq, dev_instance);
362 }
363 }
364 return IRQ_HANDLED;
365}
366
339void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac) 367void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
340{ 368{
341 /* Spinlock-type semantics: only one caller disable poll at a time */ 369 /* Spinlock-type semantics: only one caller disable poll at a time */
@@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
493 unsigned int dcr_base; 521 unsigned int dcr_base;
494 const u32 *prop; 522 const u32 *prop;
495 u32 cfg; 523 u32 cfg;
524 unsigned long irqflags;
525 irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
496 526
497 mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL); 527 mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
498 if (!mal) { 528 if (!mal) {
@@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
542 goto fail; 572 goto fail;
543 } 573 }
544 574
575 if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
576 mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
577 MAL_FTR_COMMON_ERR_INT);
578
545 mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0); 579 mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
546 mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1); 580 mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
547 mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2); 581 mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
548 mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3); 582
549 mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4); 583 if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
584 mal->txde_irq = mal->rxde_irq = mal->serr_irq;
585 } else {
586 mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
587 mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
588 }
589
550 if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ || 590 if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
551 mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ || 591 mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
552 mal->rxde_irq == NO_IRQ) { 592 mal->rxde_irq == NO_IRQ) {
@@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
608 sizeof(struct mal_descriptor) * 648 sizeof(struct mal_descriptor) *
609 mal_rx_bd_offset(mal, i)); 649 mal_rx_bd_offset(mal, i));
610 650
611 err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal); 651 if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
652 irqflags = IRQF_SHARED;
653 hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
654 } else {
655 irqflags = 0;
656 hdlr_serr = mal_serr;
657 hdlr_txde = mal_txde;
658 hdlr_rxde = mal_rxde;
659 }
660
661 err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
612 if (err) 662 if (err)
613 goto fail2; 663 goto fail2;
614 err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal); 664 err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
615 if (err) 665 if (err)
616 goto fail3; 666 goto fail3;
617 err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal); 667 err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
618 if (err) 668 if (err)
619 goto fail4; 669 goto fail4;
620 err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal); 670 err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
621 if (err) 671 if (err)
622 goto fail5; 672 goto fail5;
623 err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal); 673 err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);