diff options
author | David S. Miller <davem@davemloft.net> | 2019-09-01 15:16:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-09-01 15:16:38 -0400 |
commit | 4bc61b0b16955322576265724ab0a0075a30dc84 (patch) | |
tree | 4ed06a60199887ca6303fe3acd5d0fcf76af5bde | |
parent | b943e03341e69cfd384ceabbb4efc28a82f69e0c (diff) | |
parent | 45de77ff8286156f78ac2beef03f6088bb3e451b (diff) |
Merge branch 'net-dsa-mv88e6xxx-centralize-SERDES-IRQ-handling'
Vivien Didelot says:
====================
net: dsa: mv88e6xxx: centralize SERDES IRQ handling
Following Marek's work on the abstraction of the SERDES lanes mapping, this
series trades the .serdes_irq_setup and .serdes_irq_free callbacks for new
.serdes_irq_mapping, .serdes_irq_enable and .serdes_irq_status operations.
This has the benefit to limit the various SERDES implementations to simple
register accesses only; centralize the IRQ handling and mutex locking logic;
as well as reducing boilerplate in the driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 141 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.h | 15 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/port.c | 21 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 382 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.h | 107 |
5 files changed, 315 insertions, 351 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index c648f9fbfa59..30365a54c31b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -2054,27 +2054,93 @@ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port) | |||
2054 | return 0; | 2054 | return 0; |
2055 | } | 2055 | } |
2056 | 2056 | ||
2057 | static irqreturn_t mv88e6xxx_serdes_irq_thread_fn(int irq, void *dev_id) | ||
2058 | { | ||
2059 | struct mv88e6xxx_port *mvp = dev_id; | ||
2060 | struct mv88e6xxx_chip *chip = mvp->chip; | ||
2061 | irqreturn_t ret = IRQ_NONE; | ||
2062 | int port = mvp->port; | ||
2063 | u8 lane; | ||
2064 | |||
2065 | mv88e6xxx_reg_lock(chip); | ||
2066 | lane = mv88e6xxx_serdes_get_lane(chip, port); | ||
2067 | if (lane) | ||
2068 | ret = mv88e6xxx_serdes_irq_status(chip, port, lane); | ||
2069 | mv88e6xxx_reg_unlock(chip); | ||
2070 | |||
2071 | return ret; | ||
2072 | } | ||
2073 | |||
2074 | static int mv88e6xxx_serdes_irq_request(struct mv88e6xxx_chip *chip, int port, | ||
2075 | u8 lane) | ||
2076 | { | ||
2077 | struct mv88e6xxx_port *dev_id = &chip->ports[port]; | ||
2078 | unsigned int irq; | ||
2079 | int err; | ||
2080 | |||
2081 | /* Nothing to request if this SERDES port has no IRQ */ | ||
2082 | irq = mv88e6xxx_serdes_irq_mapping(chip, port); | ||
2083 | if (!irq) | ||
2084 | return 0; | ||
2085 | |||
2086 | /* Requesting the IRQ will trigger IRQ callbacks, so release the lock */ | ||
2087 | mv88e6xxx_reg_unlock(chip); | ||
2088 | err = request_threaded_irq(irq, NULL, mv88e6xxx_serdes_irq_thread_fn, | ||
2089 | IRQF_ONESHOT, "mv88e6xxx-serdes", dev_id); | ||
2090 | mv88e6xxx_reg_lock(chip); | ||
2091 | if (err) | ||
2092 | return err; | ||
2093 | |||
2094 | dev_id->serdes_irq = irq; | ||
2095 | |||
2096 | return mv88e6xxx_serdes_irq_enable(chip, port, lane); | ||
2097 | } | ||
2098 | |||
2099 | static int mv88e6xxx_serdes_irq_free(struct mv88e6xxx_chip *chip, int port, | ||
2100 | u8 lane) | ||
2101 | { | ||
2102 | struct mv88e6xxx_port *dev_id = &chip->ports[port]; | ||
2103 | unsigned int irq = dev_id->serdes_irq; | ||
2104 | int err; | ||
2105 | |||
2106 | /* Nothing to free if no IRQ has been requested */ | ||
2107 | if (!irq) | ||
2108 | return 0; | ||
2109 | |||
2110 | err = mv88e6xxx_serdes_irq_disable(chip, port, lane); | ||
2111 | |||
2112 | /* Freeing the IRQ will trigger IRQ callbacks, so release the lock */ | ||
2113 | mv88e6xxx_reg_unlock(chip); | ||
2114 | free_irq(irq, dev_id); | ||
2115 | mv88e6xxx_reg_lock(chip); | ||
2116 | |||
2117 | dev_id->serdes_irq = 0; | ||
2118 | |||
2119 | return err; | ||
2120 | } | ||
2121 | |||
2057 | static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port, | 2122 | static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port, |
2058 | bool on) | 2123 | bool on) |
2059 | { | 2124 | { |
2125 | u8 lane; | ||
2060 | int err; | 2126 | int err; |
2061 | 2127 | ||
2062 | if (!chip->info->ops->serdes_power) | 2128 | lane = mv88e6xxx_serdes_get_lane(chip, port); |
2129 | if (!lane) | ||
2063 | return 0; | 2130 | return 0; |
2064 | 2131 | ||
2065 | if (on) { | 2132 | if (on) { |
2066 | err = chip->info->ops->serdes_power(chip, port, true); | 2133 | err = mv88e6xxx_serdes_power_up(chip, port, lane); |
2067 | if (err) | 2134 | if (err) |
2068 | return err; | 2135 | return err; |
2069 | 2136 | ||
2070 | if (chip->info->ops->serdes_irq_setup) | 2137 | err = mv88e6xxx_serdes_irq_request(chip, port, lane); |
2071 | err = chip->info->ops->serdes_irq_setup(chip, port); | ||
2072 | } else { | 2138 | } else { |
2073 | if (chip->info->ops->serdes_irq_free && | 2139 | err = mv88e6xxx_serdes_irq_free(chip, port, lane); |
2074 | chip->ports[port].serdes_irq) | 2140 | if (err) |
2075 | chip->info->ops->serdes_irq_free(chip, port); | 2141 | return err; |
2076 | 2142 | ||
2077 | err = chip->info->ops->serdes_power(chip, port, false); | 2143 | err = mv88e6xxx_serdes_power_down(chip, port, lane); |
2078 | } | 2144 | } |
2079 | 2145 | ||
2080 | return err; | 2146 | return err; |
@@ -2931,8 +2997,9 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { | |||
2931 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 2997 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
2932 | .serdes_power = mv88e6390_serdes_power, | 2998 | .serdes_power = mv88e6390_serdes_power, |
2933 | .serdes_get_lane = mv88e6341_serdes_get_lane, | 2999 | .serdes_get_lane = mv88e6341_serdes_get_lane, |
2934 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3000 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
2935 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3001 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3002 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
2936 | .gpio_ops = &mv88e6352_gpio_ops, | 3003 | .gpio_ops = &mv88e6352_gpio_ops, |
2937 | .phylink_validate = mv88e6341_phylink_validate, | 3004 | .phylink_validate = mv88e6341_phylink_validate, |
2938 | }; | 3005 | }; |
@@ -3092,6 +3159,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { | |||
3092 | .rmu_disable = mv88e6352_g1_rmu_disable, | 3159 | .rmu_disable = mv88e6352_g1_rmu_disable, |
3093 | .vtu_getnext = mv88e6352_g1_vtu_getnext, | 3160 | .vtu_getnext = mv88e6352_g1_vtu_getnext, |
3094 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 3161 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
3162 | .serdes_get_lane = mv88e6352_serdes_get_lane, | ||
3095 | .serdes_power = mv88e6352_serdes_power, | 3163 | .serdes_power = mv88e6352_serdes_power, |
3096 | .gpio_ops = &mv88e6352_gpio_ops, | 3164 | .gpio_ops = &mv88e6352_gpio_ops, |
3097 | .phylink_validate = mv88e6352_phylink_validate, | 3165 | .phylink_validate = mv88e6352_phylink_validate, |
@@ -3177,9 +3245,11 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { | |||
3177 | .rmu_disable = mv88e6352_g1_rmu_disable, | 3245 | .rmu_disable = mv88e6352_g1_rmu_disable, |
3178 | .vtu_getnext = mv88e6352_g1_vtu_getnext, | 3246 | .vtu_getnext = mv88e6352_g1_vtu_getnext, |
3179 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 3247 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
3248 | .serdes_get_lane = mv88e6352_serdes_get_lane, | ||
3180 | .serdes_power = mv88e6352_serdes_power, | 3249 | .serdes_power = mv88e6352_serdes_power, |
3181 | .serdes_irq_setup = mv88e6352_serdes_irq_setup, | 3250 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, |
3182 | .serdes_irq_free = mv88e6352_serdes_irq_free, | 3251 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, |
3252 | .serdes_irq_status = mv88e6352_serdes_irq_status, | ||
3183 | .gpio_ops = &mv88e6352_gpio_ops, | 3253 | .gpio_ops = &mv88e6352_gpio_ops, |
3184 | .phylink_validate = mv88e6352_phylink_validate, | 3254 | .phylink_validate = mv88e6352_phylink_validate, |
3185 | }; | 3255 | }; |
@@ -3261,8 +3331,9 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { | |||
3261 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3331 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3262 | .serdes_power = mv88e6390_serdes_power, | 3332 | .serdes_power = mv88e6390_serdes_power, |
3263 | .serdes_get_lane = mv88e6390_serdes_get_lane, | 3333 | .serdes_get_lane = mv88e6390_serdes_get_lane, |
3264 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3334 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3265 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3335 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3336 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3266 | .gpio_ops = &mv88e6352_gpio_ops, | 3337 | .gpio_ops = &mv88e6352_gpio_ops, |
3267 | .phylink_validate = mv88e6390_phylink_validate, | 3338 | .phylink_validate = mv88e6390_phylink_validate, |
3268 | }; | 3339 | }; |
@@ -3308,8 +3379,9 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { | |||
3308 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3379 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3309 | .serdes_power = mv88e6390_serdes_power, | 3380 | .serdes_power = mv88e6390_serdes_power, |
3310 | .serdes_get_lane = mv88e6390x_serdes_get_lane, | 3381 | .serdes_get_lane = mv88e6390x_serdes_get_lane, |
3311 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3382 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3312 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3383 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3384 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3313 | .gpio_ops = &mv88e6352_gpio_ops, | 3385 | .gpio_ops = &mv88e6352_gpio_ops, |
3314 | .phylink_validate = mv88e6390x_phylink_validate, | 3386 | .phylink_validate = mv88e6390x_phylink_validate, |
3315 | }; | 3387 | }; |
@@ -3355,8 +3427,9 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { | |||
3355 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3427 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3356 | .serdes_power = mv88e6390_serdes_power, | 3428 | .serdes_power = mv88e6390_serdes_power, |
3357 | .serdes_get_lane = mv88e6390_serdes_get_lane, | 3429 | .serdes_get_lane = mv88e6390_serdes_get_lane, |
3358 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3430 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3359 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3431 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3432 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3360 | .avb_ops = &mv88e6390_avb_ops, | 3433 | .avb_ops = &mv88e6390_avb_ops, |
3361 | .ptp_ops = &mv88e6352_ptp_ops, | 3434 | .ptp_ops = &mv88e6352_ptp_ops, |
3362 | .phylink_validate = mv88e6390_phylink_validate, | 3435 | .phylink_validate = mv88e6390_phylink_validate, |
@@ -3402,9 +3475,11 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { | |||
3402 | .rmu_disable = mv88e6352_g1_rmu_disable, | 3475 | .rmu_disable = mv88e6352_g1_rmu_disable, |
3403 | .vtu_getnext = mv88e6352_g1_vtu_getnext, | 3476 | .vtu_getnext = mv88e6352_g1_vtu_getnext, |
3404 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 3477 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
3478 | .serdes_get_lane = mv88e6352_serdes_get_lane, | ||
3405 | .serdes_power = mv88e6352_serdes_power, | 3479 | .serdes_power = mv88e6352_serdes_power, |
3406 | .serdes_irq_setup = mv88e6352_serdes_irq_setup, | 3480 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, |
3407 | .serdes_irq_free = mv88e6352_serdes_irq_free, | 3481 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, |
3482 | .serdes_irq_status = mv88e6352_serdes_irq_status, | ||
3408 | .gpio_ops = &mv88e6352_gpio_ops, | 3483 | .gpio_ops = &mv88e6352_gpio_ops, |
3409 | .avb_ops = &mv88e6352_avb_ops, | 3484 | .avb_ops = &mv88e6352_avb_ops, |
3410 | .ptp_ops = &mv88e6352_ptp_ops, | 3485 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3492,8 +3567,9 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { | |||
3492 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3567 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3493 | .serdes_power = mv88e6390_serdes_power, | 3568 | .serdes_power = mv88e6390_serdes_power, |
3494 | .serdes_get_lane = mv88e6390_serdes_get_lane, | 3569 | .serdes_get_lane = mv88e6390_serdes_get_lane, |
3495 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3570 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3496 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3571 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3572 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3497 | .gpio_ops = &mv88e6352_gpio_ops, | 3573 | .gpio_ops = &mv88e6352_gpio_ops, |
3498 | .avb_ops = &mv88e6390_avb_ops, | 3574 | .avb_ops = &mv88e6390_avb_ops, |
3499 | .ptp_ops = &mv88e6352_ptp_ops, | 3575 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3629,8 +3705,9 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { | |||
3629 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 3705 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
3630 | .serdes_power = mv88e6390_serdes_power, | 3706 | .serdes_power = mv88e6390_serdes_power, |
3631 | .serdes_get_lane = mv88e6341_serdes_get_lane, | 3707 | .serdes_get_lane = mv88e6341_serdes_get_lane, |
3632 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3708 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3633 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3709 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3710 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3634 | .gpio_ops = &mv88e6352_gpio_ops, | 3711 | .gpio_ops = &mv88e6352_gpio_ops, |
3635 | .avb_ops = &mv88e6390_avb_ops, | 3712 | .avb_ops = &mv88e6390_avb_ops, |
3636 | .ptp_ops = &mv88e6352_ptp_ops, | 3713 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3759,9 +3836,11 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { | |||
3759 | .rmu_disable = mv88e6352_g1_rmu_disable, | 3836 | .rmu_disable = mv88e6352_g1_rmu_disable, |
3760 | .vtu_getnext = mv88e6352_g1_vtu_getnext, | 3837 | .vtu_getnext = mv88e6352_g1_vtu_getnext, |
3761 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 3838 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
3839 | .serdes_get_lane = mv88e6352_serdes_get_lane, | ||
3762 | .serdes_power = mv88e6352_serdes_power, | 3840 | .serdes_power = mv88e6352_serdes_power, |
3763 | .serdes_irq_setup = mv88e6352_serdes_irq_setup, | 3841 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, |
3764 | .serdes_irq_free = mv88e6352_serdes_irq_free, | 3842 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, |
3843 | .serdes_irq_status = mv88e6352_serdes_irq_status, | ||
3765 | .gpio_ops = &mv88e6352_gpio_ops, | 3844 | .gpio_ops = &mv88e6352_gpio_ops, |
3766 | .avb_ops = &mv88e6352_avb_ops, | 3845 | .avb_ops = &mv88e6352_avb_ops, |
3767 | .ptp_ops = &mv88e6352_ptp_ops, | 3846 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3814,8 +3893,9 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { | |||
3814 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3893 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3815 | .serdes_power = mv88e6390_serdes_power, | 3894 | .serdes_power = mv88e6390_serdes_power, |
3816 | .serdes_get_lane = mv88e6390_serdes_get_lane, | 3895 | .serdes_get_lane = mv88e6390_serdes_get_lane, |
3817 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3896 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3818 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3897 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3898 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3819 | .gpio_ops = &mv88e6352_gpio_ops, | 3899 | .gpio_ops = &mv88e6352_gpio_ops, |
3820 | .avb_ops = &mv88e6390_avb_ops, | 3900 | .avb_ops = &mv88e6390_avb_ops, |
3821 | .ptp_ops = &mv88e6352_ptp_ops, | 3901 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3865,8 +3945,9 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { | |||
3865 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3945 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3866 | .serdes_power = mv88e6390_serdes_power, | 3946 | .serdes_power = mv88e6390_serdes_power, |
3867 | .serdes_get_lane = mv88e6390x_serdes_get_lane, | 3947 | .serdes_get_lane = mv88e6390x_serdes_get_lane, |
3868 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | 3948 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3869 | .serdes_irq_free = mv88e6390_serdes_irq_free, | 3949 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3950 | .serdes_irq_status = mv88e6390_serdes_irq_status, | ||
3870 | .gpio_ops = &mv88e6352_gpio_ops, | 3951 | .gpio_ops = &mv88e6352_gpio_ops, |
3871 | .avb_ops = &mv88e6390_avb_ops, | 3952 | .avb_ops = &mv88e6390_avb_ops, |
3872 | .ptp_ops = &mv88e6352_ptp_ops, | 3953 | .ptp_ops = &mv88e6352_ptp_ops, |
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 421e8b84bec3..6bc0a4e4fe7b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h | |||
@@ -199,7 +199,7 @@ struct mv88e6xxx_port { | |||
199 | u64 vtu_member_violation; | 199 | u64 vtu_member_violation; |
200 | u64 vtu_miss_violation; | 200 | u64 vtu_miss_violation; |
201 | u8 cmode; | 201 | u8 cmode; |
202 | int serdes_irq; | 202 | unsigned int serdes_irq; |
203 | }; | 203 | }; |
204 | 204 | ||
205 | struct mv88e6xxx_chip { | 205 | struct mv88e6xxx_chip { |
@@ -441,14 +441,19 @@ struct mv88e6xxx_ops { | |||
441 | int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); | 441 | int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); |
442 | 442 | ||
443 | /* Power on/off a SERDES interface */ | 443 | /* Power on/off a SERDES interface */ |
444 | int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on); | 444 | int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, u8 lane, |
445 | bool up); | ||
445 | 446 | ||
446 | /* SERDES lane mapping */ | 447 | /* SERDES lane mapping */ |
447 | int (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port, u8 *lane); | 448 | u8 (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port); |
448 | 449 | ||
449 | /* SERDES interrupt handling */ | 450 | /* SERDES interrupt handling */ |
450 | int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port); | 451 | unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip, |
451 | void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port); | 452 | int port); |
453 | int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane, | ||
454 | bool enable); | ||
455 | irqreturn_t (*serdes_irq_status)(struct mv88e6xxx_chip *chip, int port, | ||
456 | u8 lane); | ||
452 | 457 | ||
453 | /* Statistics from the SERDES interface */ | 458 | /* Statistics from the SERDES interface */ |
454 | int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); | 459 | int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); |
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 4f841335ea32..04006344adb2 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c | |||
@@ -431,18 +431,15 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, | |||
431 | if (cmode == chip->ports[port].cmode) | 431 | if (cmode == chip->ports[port].cmode) |
432 | return 0; | 432 | return 0; |
433 | 433 | ||
434 | err = mv88e6xxx_serdes_get_lane(chip, port, &lane); | 434 | lane = mv88e6xxx_serdes_get_lane(chip, port); |
435 | if (err && err != -ENODEV) | 435 | if (lane) { |
436 | return err; | ||
437 | |||
438 | if (err != -ENODEV) { | ||
439 | if (chip->ports[port].serdes_irq) { | 436 | if (chip->ports[port].serdes_irq) { |
440 | err = mv88e6390_serdes_irq_disable(chip, port, lane); | 437 | err = mv88e6xxx_serdes_irq_disable(chip, port, lane); |
441 | if (err) | 438 | if (err) |
442 | return err; | 439 | return err; |
443 | } | 440 | } |
444 | 441 | ||
445 | err = mv88e6390_serdes_power(chip, port, false); | 442 | err = mv88e6xxx_serdes_power_down(chip, port, lane); |
446 | if (err) | 443 | if (err) |
447 | return err; | 444 | return err; |
448 | } | 445 | } |
@@ -463,16 +460,16 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, | |||
463 | 460 | ||
464 | chip->ports[port].cmode = cmode; | 461 | chip->ports[port].cmode = cmode; |
465 | 462 | ||
466 | err = mv88e6xxx_serdes_get_lane(chip, port, &lane); | 463 | lane = mv88e6xxx_serdes_get_lane(chip, port); |
467 | if (err) | 464 | if (!lane) |
468 | return err; | 465 | return -ENODEV; |
469 | 466 | ||
470 | err = mv88e6390_serdes_power(chip, port, true); | 467 | err = mv88e6xxx_serdes_power_up(chip, port, lane); |
471 | if (err) | 468 | if (err) |
472 | return err; | 469 | return err; |
473 | 470 | ||
474 | if (chip->ports[port].serdes_irq) { | 471 | if (chip->ports[port].serdes_irq) { |
475 | err = mv88e6390_serdes_irq_enable(chip, port, lane); | 472 | err = mv88e6xxx_serdes_irq_enable(chip, port, lane); |
476 | if (err) | 473 | if (err) |
477 | return err; | 474 | return err; |
478 | } | 475 | } |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 38c0da2492c0..902feb398746 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c | |||
@@ -49,7 +49,8 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, | |||
49 | return mv88e6xxx_phy_write(chip, lane, reg_c45, val); | 49 | return mv88e6xxx_phy_write(chip, lane, reg_c45, val); |
50 | } | 50 | } |
51 | 51 | ||
52 | static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on) | 52 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, |
53 | bool up) | ||
53 | { | 54 | { |
54 | u16 val, new_val; | 55 | u16 val, new_val; |
55 | int err; | 56 | int err; |
@@ -58,7 +59,7 @@ static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on) | |||
58 | if (err) | 59 | if (err) |
59 | return err; | 60 | return err; |
60 | 61 | ||
61 | if (on) | 62 | if (up) |
62 | new_val = val & ~BMCR_PDOWN; | 63 | new_val = val & ~BMCR_PDOWN; |
63 | else | 64 | else |
64 | new_val = val | BMCR_PDOWN; | 65 | new_val = val | BMCR_PDOWN; |
@@ -69,29 +70,25 @@ static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on) | |||
69 | return err; | 70 | return err; |
70 | } | 71 | } |
71 | 72 | ||
72 | static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port) | 73 | u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
73 | { | 74 | { |
74 | u8 cmode = chip->ports[port].cmode; | 75 | u8 cmode = chip->ports[port].cmode; |
76 | u8 lane = 0; | ||
75 | 77 | ||
76 | if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) || | 78 | if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) || |
77 | (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) || | 79 | (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) || |
78 | (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) | 80 | (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) |
79 | return true; | 81 | lane = 0xff; /* Unused */ |
80 | 82 | ||
81 | return false; | 83 | return lane; |
82 | } | 84 | } |
83 | 85 | ||
84 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) | 86 | static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port) |
85 | { | 87 | { |
86 | int err; | 88 | if (mv88e6xxx_serdes_get_lane(chip, port)) |
87 | 89 | return true; | |
88 | if (mv88e6352_port_has_serdes(chip, port)) { | ||
89 | err = mv88e6352_serdes_power_set(chip, on); | ||
90 | if (err < 0) | ||
91 | return err; | ||
92 | } | ||
93 | 90 | ||
94 | return 0; | 91 | return false; |
95 | } | 92 | } |
96 | 93 | ||
97 | struct mv88e6352_serdes_hw_stat { | 94 | struct mv88e6352_serdes_hw_stat { |
@@ -186,254 +183,178 @@ static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port) | |||
186 | struct dsa_switch *ds = chip->ds; | 183 | struct dsa_switch *ds = chip->ds; |
187 | u16 status; | 184 | u16 status; |
188 | bool up; | 185 | bool up; |
186 | int err; | ||
189 | 187 | ||
190 | mv88e6352_serdes_read(chip, MII_BMSR, &status); | 188 | err = mv88e6352_serdes_read(chip, MII_BMSR, &status); |
189 | if (err) | ||
190 | return; | ||
191 | 191 | ||
192 | /* Status must be read twice in order to give the current link | 192 | /* Status must be read twice in order to give the current link |
193 | * status. Otherwise the change in link status since the last | 193 | * status. Otherwise the change in link status since the last |
194 | * read of the register is returned. | 194 | * read of the register is returned. |
195 | */ | 195 | */ |
196 | mv88e6352_serdes_read(chip, MII_BMSR, &status); | 196 | err = mv88e6352_serdes_read(chip, MII_BMSR, &status); |
197 | if (err) | ||
198 | return; | ||
197 | 199 | ||
198 | up = status & BMSR_LSTATUS; | 200 | up = status & BMSR_LSTATUS; |
199 | 201 | ||
200 | dsa_port_phylink_mac_change(ds, port, up); | 202 | dsa_port_phylink_mac_change(ds, port, up); |
201 | } | 203 | } |
202 | 204 | ||
203 | static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id) | 205 | irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, |
206 | u8 lane) | ||
204 | { | 207 | { |
205 | struct mv88e6xxx_port *port = dev_id; | ||
206 | struct mv88e6xxx_chip *chip = port->chip; | ||
207 | irqreturn_t ret = IRQ_NONE; | 208 | irqreturn_t ret = IRQ_NONE; |
208 | u16 status; | 209 | u16 status; |
209 | int err; | 210 | int err; |
210 | 211 | ||
211 | mv88e6xxx_reg_lock(chip); | ||
212 | |||
213 | err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); | 212 | err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); |
214 | if (err) | 213 | if (err) |
215 | goto out; | 214 | return ret; |
216 | 215 | ||
217 | if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { | 216 | if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { |
218 | ret = IRQ_HANDLED; | 217 | ret = IRQ_HANDLED; |
219 | mv88e6352_serdes_irq_link(chip, port->port); | 218 | mv88e6352_serdes_irq_link(chip, port); |
220 | } | 219 | } |
221 | out: | ||
222 | mv88e6xxx_reg_unlock(chip); | ||
223 | 220 | ||
224 | return ret; | 221 | return ret; |
225 | } | 222 | } |
226 | 223 | ||
227 | static int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip) | 224 | int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, |
228 | { | 225 | bool enable) |
229 | return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, | ||
230 | MV88E6352_SERDES_INT_LINK_CHANGE); | ||
231 | } | ||
232 | |||
233 | static int mv88e6352_serdes_irq_disable(struct mv88e6xxx_chip *chip) | ||
234 | { | 226 | { |
235 | return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 0); | 227 | u16 val = 0; |
236 | } | ||
237 | |||
238 | int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) | ||
239 | { | ||
240 | int err; | ||
241 | |||
242 | if (!mv88e6352_port_has_serdes(chip, port)) | ||
243 | return 0; | ||
244 | |||
245 | chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain, | ||
246 | MV88E6352_SERDES_IRQ); | ||
247 | if (chip->ports[port].serdes_irq < 0) { | ||
248 | dev_err(chip->dev, "Unable to map SERDES irq: %d\n", | ||
249 | chip->ports[port].serdes_irq); | ||
250 | return chip->ports[port].serdes_irq; | ||
251 | } | ||
252 | |||
253 | /* Requesting the IRQ will trigger irq callbacks. So we cannot | ||
254 | * hold the reg_lock. | ||
255 | */ | ||
256 | mv88e6xxx_reg_unlock(chip); | ||
257 | err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, | ||
258 | mv88e6352_serdes_thread_fn, | ||
259 | IRQF_ONESHOT, "mv88e6xxx-serdes", | ||
260 | &chip->ports[port]); | ||
261 | mv88e6xxx_reg_lock(chip); | ||
262 | 228 | ||
263 | if (err) { | 229 | if (enable) |
264 | dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", | 230 | val |= MV88E6352_SERDES_INT_LINK_CHANGE; |
265 | err); | ||
266 | return err; | ||
267 | } | ||
268 | 231 | ||
269 | return mv88e6352_serdes_irq_enable(chip); | 232 | return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val); |
270 | } | 233 | } |
271 | 234 | ||
272 | void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) | 235 | unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) |
273 | { | 236 | { |
274 | if (!mv88e6352_port_has_serdes(chip, port)) | 237 | return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); |
275 | return; | ||
276 | |||
277 | mv88e6352_serdes_irq_disable(chip); | ||
278 | |||
279 | /* Freeing the IRQ will trigger irq callbacks. So we cannot | ||
280 | * hold the reg_lock. | ||
281 | */ | ||
282 | mv88e6xxx_reg_unlock(chip); | ||
283 | free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); | ||
284 | mv88e6xxx_reg_lock(chip); | ||
285 | |||
286 | chip->ports[port].serdes_irq = 0; | ||
287 | } | 238 | } |
288 | 239 | ||
289 | int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane) | 240 | u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
290 | { | 241 | { |
291 | u8 cmode = chip->ports[port].cmode; | 242 | u8 cmode = chip->ports[port].cmode; |
243 | u8 lane = 0; | ||
292 | 244 | ||
293 | if (port != 5) | 245 | switch (port) { |
294 | return -ENODEV; | 246 | case 5: |
295 | 247 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | |
296 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 248 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || |
297 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || | 249 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) |
298 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { | 250 | lane = MV88E6341_PORT5_LANE; |
299 | *lane = MV88E6341_PORT5_LANE; | 251 | break; |
300 | return 0; | ||
301 | } | 252 | } |
302 | 253 | ||
303 | return -ENODEV; | 254 | return lane; |
304 | } | 255 | } |
305 | 256 | ||
306 | int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane) | 257 | u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
307 | { | 258 | { |
308 | u8 cmode = chip->ports[port].cmode; | 259 | u8 cmode = chip->ports[port].cmode; |
260 | u8 lane = 0; | ||
309 | 261 | ||
310 | switch (port) { | 262 | switch (port) { |
311 | case 9: | 263 | case 9: |
312 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 264 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
313 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || | 265 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || |
314 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { | 266 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) |
315 | *lane = MV88E6390_PORT9_LANE0; | 267 | lane = MV88E6390_PORT9_LANE0; |
316 | return 0; | ||
317 | } | ||
318 | break; | 268 | break; |
319 | case 10: | 269 | case 10: |
320 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 270 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
321 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || | 271 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || |
322 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { | 272 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) |
323 | *lane = MV88E6390_PORT10_LANE0; | 273 | lane = MV88E6390_PORT10_LANE0; |
324 | return 0; | ||
325 | } | ||
326 | break; | ||
327 | default: | ||
328 | break; | 274 | break; |
329 | } | 275 | } |
330 | 276 | ||
331 | return -ENODEV; | 277 | return lane; |
332 | } | 278 | } |
333 | 279 | ||
334 | int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane) | 280 | u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
335 | { | 281 | { |
336 | u8 cmode_port9, cmode_port10, cmode_port; | 282 | u8 cmode_port = chip->ports[port].cmode; |
337 | 283 | u8 cmode_port10 = chip->ports[10].cmode; | |
338 | cmode_port9 = chip->ports[9].cmode; | 284 | u8 cmode_port9 = chip->ports[9].cmode; |
339 | cmode_port10 = chip->ports[10].cmode; | 285 | u8 lane = 0; |
340 | cmode_port = chip->ports[port].cmode; | ||
341 | 286 | ||
342 | switch (port) { | 287 | switch (port) { |
343 | case 2: | 288 | case 2: |
344 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 289 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
345 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 290 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
346 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { | 291 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) |
347 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) { | 292 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) |
348 | *lane = MV88E6390_PORT9_LANE1; | 293 | lane = MV88E6390_PORT9_LANE1; |
349 | return 0; | ||
350 | } | ||
351 | } | ||
352 | break; | 294 | break; |
353 | case 3: | 295 | case 3: |
354 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 296 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
355 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 297 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
356 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || | 298 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || |
357 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { | 299 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) |
358 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) { | 300 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) |
359 | *lane = MV88E6390_PORT9_LANE2; | 301 | lane = MV88E6390_PORT9_LANE2; |
360 | return 0; | ||
361 | } | ||
362 | } | ||
363 | break; | 302 | break; |
364 | case 4: | 303 | case 4: |
365 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 304 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
366 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 305 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
367 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || | 306 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || |
368 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { | 307 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) |
369 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) { | 308 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) |
370 | *lane = MV88E6390_PORT9_LANE3; | 309 | lane = MV88E6390_PORT9_LANE3; |
371 | return 0; | ||
372 | } | ||
373 | } | ||
374 | break; | 310 | break; |
375 | case 5: | 311 | case 5: |
376 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 312 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
377 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 313 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
378 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) { | 314 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) |
379 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) { | 315 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) |
380 | *lane = MV88E6390_PORT10_LANE1; | 316 | lane = MV88E6390_PORT10_LANE1; |
381 | return 0; | ||
382 | } | ||
383 | } | ||
384 | break; | 317 | break; |
385 | case 6: | 318 | case 6: |
386 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 319 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
387 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 320 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
388 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || | 321 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || |
389 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { | 322 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) |
390 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) { | 323 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) |
391 | *lane = MV88E6390_PORT10_LANE2; | 324 | lane = MV88E6390_PORT10_LANE2; |
392 | return 0; | ||
393 | } | ||
394 | } | ||
395 | break; | 325 | break; |
396 | case 7: | 326 | case 7: |
397 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 327 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
398 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 328 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
399 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || | 329 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || |
400 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { | 330 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) |
401 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) { | 331 | if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) |
402 | *lane = MV88E6390_PORT10_LANE3; | 332 | lane = MV88E6390_PORT10_LANE3; |
403 | return 0; | ||
404 | } | ||
405 | } | ||
406 | break; | 333 | break; |
407 | case 9: | 334 | case 9: |
408 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 335 | if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
409 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 336 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
410 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || | 337 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || |
411 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || | 338 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || |
412 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { | 339 | cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) |
413 | *lane = MV88E6390_PORT9_LANE0; | 340 | lane = MV88E6390_PORT9_LANE0; |
414 | return 0; | ||
415 | } | ||
416 | break; | 341 | break; |
417 | case 10: | 342 | case 10: |
418 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || | 343 | if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || |
419 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || | 344 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || |
420 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || | 345 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || |
421 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || | 346 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || |
422 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) { | 347 | cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) |
423 | *lane = MV88E6390_PORT10_LANE0; | 348 | lane = MV88E6390_PORT10_LANE0; |
424 | return 0; | ||
425 | } | ||
426 | break; | ||
427 | default: | ||
428 | break; | 349 | break; |
429 | } | 350 | } |
430 | 351 | ||
431 | return -ENODEV; | 352 | return lane; |
432 | } | 353 | } |
433 | 354 | ||
434 | /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ | 355 | /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */ |
435 | static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, | 356 | static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, |
436 | bool on) | 357 | bool up) |
437 | { | 358 | { |
438 | u16 val, new_val; | 359 | u16 val, new_val; |
439 | int err; | 360 | int err; |
@@ -444,7 +365,7 @@ static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, | |||
444 | if (err) | 365 | if (err) |
445 | return err; | 366 | return err; |
446 | 367 | ||
447 | if (on) | 368 | if (up) |
448 | new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | | 369 | new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | |
449 | MV88E6390_PCS_CONTROL_1_LOOPBACK | | 370 | MV88E6390_PCS_CONTROL_1_LOOPBACK | |
450 | MV88E6390_PCS_CONTROL_1_PDOWN); | 371 | MV88E6390_PCS_CONTROL_1_PDOWN); |
@@ -458,9 +379,9 @@ static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, | |||
458 | return err; | 379 | return err; |
459 | } | 380 | } |
460 | 381 | ||
461 | /* Set the power on/off for SGMII and 1000Base-X */ | 382 | /* Set power up/down for SGMII and 1000Base-X */ |
462 | static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, | 383 | static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, |
463 | bool on) | 384 | bool up) |
464 | { | 385 | { |
465 | u16 val, new_val; | 386 | u16 val, new_val; |
466 | int err; | 387 | int err; |
@@ -470,7 +391,7 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, | |||
470 | if (err) | 391 | if (err) |
471 | return err; | 392 | return err; |
472 | 393 | ||
473 | if (on) | 394 | if (up) |
474 | new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | | 395 | new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | |
475 | MV88E6390_SGMII_CONTROL_LOOPBACK | | 396 | MV88E6390_SGMII_CONTROL_LOOPBACK | |
476 | MV88E6390_SGMII_CONTROL_PDOWN); | 397 | MV88E6390_SGMII_CONTROL_PDOWN); |
@@ -484,27 +405,19 @@ static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, | |||
484 | return err; | 405 | return err; |
485 | } | 406 | } |
486 | 407 | ||
487 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) | 408 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, |
409 | bool up) | ||
488 | { | 410 | { |
489 | u8 cmode = chip->ports[port].cmode; | 411 | u8 cmode = chip->ports[port].cmode; |
490 | u8 lane; | ||
491 | int err; | ||
492 | |||
493 | err = mv88e6xxx_serdes_get_lane(chip, port, &lane); | ||
494 | if (err) { | ||
495 | if (err == -ENODEV) | ||
496 | err = 0; | ||
497 | return err; | ||
498 | } | ||
499 | 412 | ||
500 | switch (cmode) { | 413 | switch (cmode) { |
501 | case MV88E6XXX_PORT_STS_CMODE_SGMII: | 414 | case MV88E6XXX_PORT_STS_CMODE_SGMII: |
502 | case MV88E6XXX_PORT_STS_CMODE_1000BASEX: | 415 | case MV88E6XXX_PORT_STS_CMODE_1000BASEX: |
503 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: | 416 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: |
504 | return mv88e6390_serdes_power_sgmii(chip, lane, on); | 417 | return mv88e6390_serdes_power_sgmii(chip, lane, up); |
505 | case MV88E6XXX_PORT_STS_CMODE_XAUI: | 418 | case MV88E6XXX_PORT_STS_CMODE_XAUI: |
506 | case MV88E6XXX_PORT_STS_CMODE_RXAUI: | 419 | case MV88E6XXX_PORT_STS_CMODE_RXAUI: |
507 | return mv88e6390_serdes_power_10g(chip, lane, on); | 420 | return mv88e6390_serdes_power_10g(chip, lane, up); |
508 | } | 421 | } |
509 | 422 | ||
510 | return 0; | 423 | return 0; |
@@ -578,51 +491,31 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, | |||
578 | } | 491 | } |
579 | 492 | ||
580 | static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, | 493 | static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, |
581 | u8 lane) | 494 | u8 lane, bool enable) |
582 | { | ||
583 | return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, | ||
584 | MV88E6390_SGMII_INT_ENABLE, | ||
585 | MV88E6390_SGMII_INT_LINK_DOWN | | ||
586 | MV88E6390_SGMII_INT_LINK_UP); | ||
587 | } | ||
588 | |||
589 | static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip, | ||
590 | u8 lane) | ||
591 | { | 495 | { |
592 | return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, | 496 | u16 val = 0; |
593 | MV88E6390_SGMII_INT_ENABLE, 0); | ||
594 | } | ||
595 | 497 | ||
596 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, | 498 | if (enable) |
597 | u8 lane) | 499 | val |= MV88E6390_SGMII_INT_LINK_DOWN | |
598 | { | 500 | MV88E6390_SGMII_INT_LINK_UP; |
599 | u8 cmode = chip->ports[port].cmode; | ||
600 | int err = 0; | ||
601 | 501 | ||
602 | switch (cmode) { | 502 | return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, |
603 | case MV88E6XXX_PORT_STS_CMODE_SGMII: | 503 | MV88E6390_SGMII_INT_ENABLE, val); |
604 | case MV88E6XXX_PORT_STS_CMODE_1000BASEX: | ||
605 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: | ||
606 | err = mv88e6390_serdes_irq_enable_sgmii(chip, lane); | ||
607 | } | ||
608 | |||
609 | return err; | ||
610 | } | 504 | } |
611 | 505 | ||
612 | int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, | 506 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, |
613 | u8 lane) | 507 | bool enable) |
614 | { | 508 | { |
615 | u8 cmode = chip->ports[port].cmode; | 509 | u8 cmode = chip->ports[port].cmode; |
616 | int err = 0; | ||
617 | 510 | ||
618 | switch (cmode) { | 511 | switch (cmode) { |
619 | case MV88E6XXX_PORT_STS_CMODE_SGMII: | 512 | case MV88E6XXX_PORT_STS_CMODE_SGMII: |
620 | case MV88E6XXX_PORT_STS_CMODE_1000BASEX: | 513 | case MV88E6XXX_PORT_STS_CMODE_1000BASEX: |
621 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: | 514 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: |
622 | err = mv88e6390_serdes_irq_disable_sgmii(chip, lane); | 515 | return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); |
623 | } | 516 | } |
624 | 517 | ||
625 | return err; | 518 | return 0; |
626 | } | 519 | } |
627 | 520 | ||
628 | static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, | 521 | static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, |
@@ -636,21 +529,13 @@ static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, | |||
636 | return err; | 529 | return err; |
637 | } | 530 | } |
638 | 531 | ||
639 | static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) | 532 | irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, |
533 | u8 lane) | ||
640 | { | 534 | { |
641 | struct mv88e6xxx_port *port = dev_id; | 535 | u8 cmode = chip->ports[port].cmode; |
642 | struct mv88e6xxx_chip *chip = port->chip; | ||
643 | irqreturn_t ret = IRQ_NONE; | 536 | irqreturn_t ret = IRQ_NONE; |
644 | u8 cmode = port->cmode; | ||
645 | u16 status; | 537 | u16 status; |
646 | int err; | 538 | int err; |
647 | u8 lane; | ||
648 | |||
649 | mv88e6xxx_reg_lock(chip); | ||
650 | |||
651 | err = mv88e6xxx_serdes_get_lane(chip, port->port, &lane); | ||
652 | if (err) | ||
653 | goto out; | ||
654 | 539 | ||
655 | switch (cmode) { | 540 | switch (cmode) { |
656 | case MV88E6XXX_PORT_STS_CMODE_SGMII: | 541 | case MV88E6XXX_PORT_STS_CMODE_SGMII: |
@@ -658,79 +543,18 @@ static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) | |||
658 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: | 543 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: |
659 | err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); | 544 | err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); |
660 | if (err) | 545 | if (err) |
661 | goto out; | 546 | return ret; |
662 | if (status & (MV88E6390_SGMII_INT_LINK_DOWN | | 547 | if (status & (MV88E6390_SGMII_INT_LINK_DOWN | |
663 | MV88E6390_SGMII_INT_LINK_UP)) { | 548 | MV88E6390_SGMII_INT_LINK_UP)) { |
664 | ret = IRQ_HANDLED; | 549 | ret = IRQ_HANDLED; |
665 | mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane); | 550 | mv88e6390_serdes_irq_link_sgmii(chip, port, lane); |
666 | } | 551 | } |
667 | } | 552 | } |
668 | out: | ||
669 | mv88e6xxx_reg_unlock(chip); | ||
670 | 553 | ||
671 | return ret; | 554 | return ret; |
672 | } | 555 | } |
673 | 556 | ||
674 | int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) | 557 | unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) |
675 | { | ||
676 | int err; | ||
677 | u8 lane; | ||
678 | |||
679 | err = mv88e6xxx_serdes_get_lane(chip, port, &lane); | ||
680 | if (err) { | ||
681 | if (err == -ENODEV) | ||
682 | err = 0; | ||
683 | return err; | ||
684 | } | ||
685 | |||
686 | chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain, | ||
687 | port); | ||
688 | if (chip->ports[port].serdes_irq < 0) { | ||
689 | dev_err(chip->dev, "Unable to map SERDES irq: %d\n", | ||
690 | chip->ports[port].serdes_irq); | ||
691 | return chip->ports[port].serdes_irq; | ||
692 | } | ||
693 | |||
694 | /* Requesting the IRQ will trigger irq callbacks. So we cannot | ||
695 | * hold the reg_lock. | ||
696 | */ | ||
697 | mv88e6xxx_reg_unlock(chip); | ||
698 | err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, | ||
699 | mv88e6390_serdes_thread_fn, | ||
700 | IRQF_ONESHOT, "mv88e6xxx-serdes", | ||
701 | &chip->ports[port]); | ||
702 | mv88e6xxx_reg_lock(chip); | ||
703 | |||
704 | if (err) { | ||
705 | dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", | ||
706 | err); | ||
707 | return err; | ||
708 | } | ||
709 | |||
710 | return mv88e6390_serdes_irq_enable(chip, port, lane); | ||
711 | } | ||
712 | |||
713 | void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) | ||
714 | { | 558 | { |
715 | int err; | 559 | return irq_find_mapping(chip->g2_irq.domain, port); |
716 | u8 lane; | ||
717 | |||
718 | err = mv88e6xxx_serdes_get_lane(chip, port, &lane); | ||
719 | if (err) { | ||
720 | if (err != -ENODEV) | ||
721 | dev_err(chip->dev, "Unable to free SERDES irq: %d\n", | ||
722 | err); | ||
723 | return; | ||
724 | } | ||
725 | |||
726 | mv88e6390_serdes_irq_disable(chip, port, lane); | ||
727 | |||
728 | /* Freeing the IRQ will trigger irq callbacks. So we cannot | ||
729 | * hold the reg_lock. | ||
730 | */ | ||
731 | mv88e6xxx_reg_unlock(chip); | ||
732 | free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); | ||
733 | mv88e6xxx_reg_lock(chip); | ||
734 | |||
735 | chip->ports[port].serdes_irq = 0; | ||
736 | } | 560 | } |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index c2e6fc3ddf8b..bd8df36ab537 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h | |||
@@ -74,37 +74,94 @@ | |||
74 | #define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11) | 74 | #define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11) |
75 | #define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10) | 75 | #define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10) |
76 | 76 | ||
77 | /* Put the SERDES lane address a port is using into *lane. If a port has | 77 | u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); |
78 | * multiple lanes, should put the first lane the port is using. If a port does | 78 | u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); |
79 | * not have a lane, return -ENODEV. | 79 | u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); |
80 | */ | 80 | u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); |
81 | static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, | 81 | unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, |
82 | int port, u8 *lane) | 82 | int port); |
83 | unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, | ||
84 | int port); | ||
85 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, | ||
86 | bool on); | ||
87 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, | ||
88 | bool on); | ||
89 | int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, | ||
90 | bool enable); | ||
91 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, | ||
92 | bool enable); | ||
93 | irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, | ||
94 | u8 lane); | ||
95 | irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, | ||
96 | u8 lane); | ||
97 | int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); | ||
98 | int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, | ||
99 | int port, uint8_t *data); | ||
100 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | ||
101 | uint64_t *data); | ||
102 | |||
103 | /* Return the (first) SERDES lane address a port is using, 0 otherwise. */ | ||
104 | static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, | ||
105 | int port) | ||
83 | { | 106 | { |
84 | if (!chip->info->ops->serdes_get_lane) | 107 | if (!chip->info->ops->serdes_get_lane) |
108 | return 0; | ||
109 | |||
110 | return chip->info->ops->serdes_get_lane(chip, port); | ||
111 | } | ||
112 | |||
113 | static inline int mv88e6xxx_serdes_power_up(struct mv88e6xxx_chip *chip, | ||
114 | int port, u8 lane) | ||
115 | { | ||
116 | if (!chip->info->ops->serdes_power) | ||
85 | return -EOPNOTSUPP; | 117 | return -EOPNOTSUPP; |
86 | 118 | ||
87 | return chip->info->ops->serdes_get_lane(chip, port, lane); | 119 | return chip->info->ops->serdes_power(chip, port, lane, true); |
88 | } | 120 | } |
89 | 121 | ||
90 | int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane); | 122 | static inline int mv88e6xxx_serdes_power_down(struct mv88e6xxx_chip *chip, |
91 | int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane); | 123 | int port, u8 lane) |
92 | int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port, u8 *lane); | 124 | { |
93 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 125 | if (!chip->info->ops->serdes_power) |
94 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 126 | return -EOPNOTSUPP; |
95 | int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port); | ||
96 | void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port); | ||
97 | int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); | ||
98 | int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, | ||
99 | int port, uint8_t *data); | ||
100 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | ||
101 | uint64_t *data); | ||
102 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, | ||
103 | u8 lane); | ||
104 | int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, | ||
105 | u8 lane); | ||
106 | int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port); | ||
107 | void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port); | ||
108 | 127 | ||
128 | return chip->info->ops->serdes_power(chip, port, lane, false); | ||
129 | } | ||
130 | |||
131 | static inline unsigned int | ||
132 | mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) | ||
133 | { | ||
134 | if (!chip->info->ops->serdes_irq_mapping) | ||
135 | return 0; | ||
136 | |||
137 | return chip->info->ops->serdes_irq_mapping(chip, port); | ||
138 | } | ||
139 | |||
140 | static inline int mv88e6xxx_serdes_irq_enable(struct mv88e6xxx_chip *chip, | ||
141 | int port, u8 lane) | ||
142 | { | ||
143 | if (!chip->info->ops->serdes_irq_enable) | ||
144 | return -EOPNOTSUPP; | ||
145 | |||
146 | return chip->info->ops->serdes_irq_enable(chip, port, lane, true); | ||
147 | } | ||
148 | |||
149 | static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip, | ||
150 | int port, u8 lane) | ||
151 | { | ||
152 | if (!chip->info->ops->serdes_irq_enable) | ||
153 | return -EOPNOTSUPP; | ||
154 | |||
155 | return chip->info->ops->serdes_irq_enable(chip, port, lane, false); | ||
156 | } | ||
157 | |||
158 | static inline irqreturn_t | ||
159 | mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, u8 lane) | ||
160 | { | ||
161 | if (!chip->info->ops->serdes_irq_status) | ||
162 | return IRQ_NONE; | ||
163 | |||
164 | return chip->info->ops->serdes_irq_status(chip, port, lane); | ||
165 | } | ||
109 | 166 | ||
110 | #endif | 167 | #endif |