aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c58
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c28
-rw-r--r--drivers/net/dsa/mv88e6xxx/mv88e6xxx.h1
3 files changed, 59 insertions, 28 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index d6d9d66b81ce..e30d0eaf2b5f 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -413,19 +413,26 @@ static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
413static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip) 413static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
414{ 414{
415 int irq, virq; 415 int irq, virq;
416 u16 mask;
417
418 mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
419 mask |= GENMASK(chip->g1_irq.nirqs, 0);
420 mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
421
422 free_irq(chip->irq, chip);
416 423
417 for (irq = 0; irq < 16; irq++) { 424 for (irq = 0; irq < 16; irq++) {
418 virq = irq_find_mapping(chip->g2_irq.domain, irq); 425 virq = irq_find_mapping(chip->g1_irq.domain, irq);
419 irq_dispose_mapping(virq); 426 irq_dispose_mapping(virq);
420 } 427 }
421 428
422 irq_domain_remove(chip->g2_irq.domain); 429 irq_domain_remove(chip->g1_irq.domain);
423} 430}
424 431
425static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) 432static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
426{ 433{
427 int err, irq; 434 int err, irq, virq;
428 u16 reg; 435 u16 reg, mask;
429 436
430 chip->g1_irq.nirqs = chip->info->g1_irqs; 437 chip->g1_irq.nirqs = chip->info->g1_irqs;
431 chip->g1_irq.domain = irq_domain_add_simple( 438 chip->g1_irq.domain = irq_domain_add_simple(
@@ -440,32 +447,41 @@ static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
440 chip->g1_irq.chip = mv88e6xxx_g1_irq_chip; 447 chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
441 chip->g1_irq.masked = ~0; 448 chip->g1_irq.masked = ~0;
442 449
443 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg); 450 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
444 if (err) 451 if (err)
445 goto out; 452 goto out_mapping;
446 453
447 reg &= ~GENMASK(chip->g1_irq.nirqs, 0); 454 mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
448 455
449 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg); 456 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
450 if (err) 457 if (err)
451 goto out; 458 goto out_disable;
452 459
453 /* Reading the interrupt status clears (most of) them */ 460 /* Reading the interrupt status clears (most of) them */
454 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg); 461 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
455 if (err) 462 if (err)
456 goto out; 463 goto out_disable;
457 464
458 err = request_threaded_irq(chip->irq, NULL, 465 err = request_threaded_irq(chip->irq, NULL,
459 mv88e6xxx_g1_irq_thread_fn, 466 mv88e6xxx_g1_irq_thread_fn,
460 IRQF_ONESHOT | IRQF_TRIGGER_FALLING, 467 IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
461 dev_name(chip->dev), chip); 468 dev_name(chip->dev), chip);
462 if (err) 469 if (err)
463 goto out; 470 goto out_disable;
464 471
465 return 0; 472 return 0;
466 473
467out: 474out_disable:
468 mv88e6xxx_g1_irq_free(chip); 475 mask |= GENMASK(chip->g1_irq.nirqs, 0);
476 mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
477
478out_mapping:
479 for (irq = 0; irq < 16; irq++) {
480 virq = irq_find_mapping(chip->g1_irq.domain, irq);
481 irq_dispose_mapping(virq);
482 }
483
484 irq_domain_remove(chip->g1_irq.domain);
469 485
470 return err; 486 return err;
471} 487}
@@ -3897,10 +3913,14 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
3897out_mdio: 3913out_mdio:
3898 mv88e6xxx_mdio_unregister(chip); 3914 mv88e6xxx_mdio_unregister(chip);
3899out_g2_irq: 3915out_g2_irq:
3900 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) 3916 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0)
3901 mv88e6xxx_g2_irq_free(chip); 3917 mv88e6xxx_g2_irq_free(chip);
3902out_g1_irq: 3918out_g1_irq:
3903 mv88e6xxx_g1_irq_free(chip); 3919 if (chip->irq > 0) {
3920 mutex_lock(&chip->reg_lock);
3921 mv88e6xxx_g1_irq_free(chip);
3922 mutex_unlock(&chip->reg_lock);
3923 }
3904out: 3924out:
3905 return err; 3925 return err;
3906} 3926}
@@ -3914,9 +3934,11 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
3914 mv88e6xxx_unregister_switch(chip); 3934 mv88e6xxx_unregister_switch(chip);
3915 mv88e6xxx_mdio_unregister(chip); 3935 mv88e6xxx_mdio_unregister(chip);
3916 3936
3917 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) 3937 if (chip->irq > 0) {
3918 mv88e6xxx_g2_irq_free(chip); 3938 if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))
3919 mv88e6xxx_g1_irq_free(chip); 3939 mv88e6xxx_g2_irq_free(chip);
3940 mv88e6xxx_g1_irq_free(chip);
3941 }
3920} 3942}
3921 3943
3922static const struct of_device_id mv88e6xxx_of_match[] = { 3944static const struct of_device_id mv88e6xxx_of_match[] = {
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 1a0b13521d13..536a27c9735f 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -507,6 +507,9 @@ void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
507{ 507{
508 int irq, virq; 508 int irq, virq;
509 509
510 free_irq(chip->device_irq, chip);
511 irq_dispose_mapping(chip->device_irq);
512
510 for (irq = 0; irq < 16; irq++) { 513 for (irq = 0; irq < 16; irq++) {
511 virq = irq_find_mapping(chip->g2_irq.domain, irq); 514 virq = irq_find_mapping(chip->g2_irq.domain, irq);
512 irq_dispose_mapping(virq); 515 irq_dispose_mapping(virq);
@@ -517,8 +520,7 @@ void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
517 520
518int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) 521int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
519{ 522{
520 int device_irq; 523 int err, irq, virq;
521 int err, irq;
522 524
523 if (!chip->dev->of_node) 525 if (!chip->dev->of_node)
524 return -EINVAL; 526 return -EINVAL;
@@ -534,22 +536,28 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
534 chip->g2_irq.chip = mv88e6xxx_g2_irq_chip; 536 chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
535 chip->g2_irq.masked = ~0; 537 chip->g2_irq.masked = ~0;
536 538
537 device_irq = irq_find_mapping(chip->g1_irq.domain, 539 chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
538 GLOBAL_STATUS_IRQ_DEVICE); 540 GLOBAL_STATUS_IRQ_DEVICE);
539 if (device_irq < 0) { 541 if (chip->device_irq < 0) {
540 err = device_irq; 542 err = chip->device_irq;
541 goto out; 543 goto out;
542 } 544 }
543 545
544 err = devm_request_threaded_irq(chip->dev, device_irq, NULL, 546 err = request_threaded_irq(chip->device_irq, NULL,
545 mv88e6xxx_g2_irq_thread_fn, 547 mv88e6xxx_g2_irq_thread_fn,
546 IRQF_ONESHOT, "mv88e6xxx-g1", chip); 548 IRQF_ONESHOT, "mv88e6xxx-g1", chip);
547 if (err) 549 if (err)
548 goto out; 550 goto out;
549 551
550 return 0; 552 return 0;
553
551out: 554out:
552 mv88e6xxx_g2_irq_free(chip); 555 for (irq = 0; irq < 16; irq++) {
556 virq = irq_find_mapping(chip->g2_irq.domain, irq);
557 irq_dispose_mapping(virq);
558 }
559
560 irq_domain_remove(chip->g2_irq.domain);
553 561
554 return err; 562 return err;
555} 563}
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 929613021eff..a3869504f881 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -714,6 +714,7 @@ struct mv88e6xxx_chip {
714 struct mv88e6xxx_irq g1_irq; 714 struct mv88e6xxx_irq g1_irq;
715 struct mv88e6xxx_irq g2_irq; 715 struct mv88e6xxx_irq g2_irq;
716 int irq; 716 int irq;
717 int device_irq;
717}; 718};
718 719
719struct mv88e6xxx_bus_ops { 720struct mv88e6xxx_bus_ops {