]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: dsa: mv88e6xxx: Add support for model-specific pre- and post-reset handlers
authorMatthias Schiffer <matthias.schiffer@ew.tq-group.com>
Tue, 23 Apr 2024 07:47:48 +0000 (09:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jun 2024 11:39:22 +0000 (13:39 +0200)
[ Upstream commit 0fdd27b9d6d7c60bd319d3497ad797934bab13cb ]

Instead of calling mv88e6xxx_g2_eeprom_wait() directly from
mv88e6xxx_hardware_reset(), add configurable pre- and post-reset hard
reset handlers. Initially, the handlers are set to
mv88e6xxx_g2_eeprom_wait() for all families that have get/set_eeprom()
to match the existing behavior. No functional change intended (except
for additional error messages on failure).

Fixes: 6ccf50d4d474 ("net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent")
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h

index 3fc120802883a3234b1980fd0e4be9325ecc3717..7484ba387d771d7f74d868b5f26643f0c0525d07 100644 (file)
@@ -2585,6 +2585,7 @@ static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
 static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
 {
        struct gpio_desc *gpiod = chip->reset;
+       int err;
 
        /* If there is a GPIO connected to the reset pin, toggle it */
        if (gpiod) {
@@ -2593,17 +2594,26 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
                 * mid-byte, causing the first EEPROM read after the reset
                 * from the wrong location resulting in the switch booting
                 * to wrong mode and inoperable.
+                * For this reason, switch families with EEPROM support
+                * generally wait for EEPROM loads to complete as their pre-
+                * and post-reset handlers.
                 */
-               if (chip->info->ops->get_eeprom)
-                       mv88e6xxx_g2_eeprom_wait(chip);
+               if (chip->info->ops->hardware_reset_pre) {
+                       err = chip->info->ops->hardware_reset_pre(chip);
+                       if (err)
+                               dev_err(chip->dev, "pre-reset error: %d\n", err);
+               }
 
                gpiod_set_value_cansleep(gpiod, 1);
                usleep_range(10000, 20000);
                gpiod_set_value_cansleep(gpiod, 0);
                usleep_range(10000, 20000);
 
-               if (chip->info->ops->get_eeprom)
-                       mv88e6xxx_g2_eeprom_wait(chip);
+               if (chip->info->ops->hardware_reset_post) {
+                       err = chip->info->ops->hardware_reset_post(chip);
+                       if (err)
+                               dev_err(chip->dev, "post-reset error: %d\n", err);
+               }
        }
 }
 
@@ -3824,6 +3834,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4006,6 +4018,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4103,6 +4117,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4201,6 +4217,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4262,6 +4280,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4321,6 +4341,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4383,6 +4405,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4438,6 +4462,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
        .watchdog_ops = &mv88e6250_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6250_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -4482,6 +4508,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4543,6 +4571,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -4586,6 +4616,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
        .set_egress_port = mv88e6095_g1_set_egress_port,
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .vtu_getnext = mv88e6185_g1_vtu_getnext,
        .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -4634,6 +4666,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4784,6 +4818,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
        .watchdog_ops = &mv88e6097_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6352_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4848,6 +4884,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4913,6 +4951,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
        .watchdog_ops = &mv88e6390_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
@@ -4981,6 +5021,8 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
        .watchdog_ops = &mv88e6393x_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
+       .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+       .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
        .reset = mv88e6352_g1_reset,
        .rmu_disable = mv88e6390_g1_rmu_disable,
        .atu_get_hash = mv88e6165_g1_atu_get_hash,
index 6b7307edaf1728a72a7c4419e6c0ac2f1177c926..6b86e7645be60de007b8664eea298fa9b6808b1e 100644 (file)
@@ -434,6 +434,12 @@ struct mv88e6xxx_ops {
        int (*ppu_enable)(struct mv88e6xxx_chip *chip);
        int (*ppu_disable)(struct mv88e6xxx_chip *chip);
 
+       /* Additional handlers to run before and after hard reset, to make sure
+        * that the switch and EEPROM are in a good state.
+        */
+       int (*hardware_reset_pre)(struct mv88e6xxx_chip *chip);
+       int (*hardware_reset_post)(struct mv88e6xxx_chip *chip);
+
        /* Switch Software Reset */
        int (*reset)(struct mv88e6xxx_chip *chip);