diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ibm_newemac/mal.c | 60 |
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 | ||
32 | static int mal_count; | 33 | static 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 | ||
348 | static 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 | |||
339 | void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac) | 367 | void 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); |