diff options
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 58 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global2.c | 28 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 1 |
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 = { | |||
| 413 | static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip) | 413 | static 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 | ||
| 425 | static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) | 432 | static 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, ®); | 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, ®); | 461 | err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, ®); |
| 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 | ||
| 467 | out: | 474 | out_disable: |
| 468 | mv88e6xxx_g1_irq_free(chip); | 475 | mask |= GENMASK(chip->g1_irq.nirqs, 0); |
| 476 | mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask); | ||
| 477 | |||
| 478 | out_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) | |||
| 3897 | out_mdio: | 3913 | out_mdio: |
| 3898 | mv88e6xxx_mdio_unregister(chip); | 3914 | mv88e6xxx_mdio_unregister(chip); |
| 3899 | out_g2_irq: | 3915 | out_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); |
| 3902 | out_g1_irq: | 3918 | out_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 | } | ||
| 3904 | out: | 3924 | out: |
| 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 | ||
| 3922 | static const struct of_device_id mv88e6xxx_of_match[] = { | 3944 | static 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 | ||
| 518 | int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) | 521 | int 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 | |||
| 551 | out: | 554 | out: |
| 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 | ||
| 719 | struct mv88e6xxx_bus_ops { | 720 | struct mv88e6xxx_bus_ops { |
