diff options
author | Vivien Didelot <vivien.didelot@gmail.com> | 2019-08-31 16:18:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-09-01 15:16:38 -0400 |
commit | 45de77ff8286156f78ac2beef03f6088bb3e451b (patch) | |
tree | 4ed06a60199887ca6303fe3acd5d0fcf76af5bde | |
parent | 907b9b9fcaef7fb193105d9d61cd795b38ee2530 (diff) |
net: dsa: mv88e6xxx: centralize SERDES IRQ handling
The .serdes_irq_setup are all following the same steps: get the SERDES
lane, get the IRQ mapping, request the IRQ, then enable it. So do
the .serdes_irq_free implementations: get the SERDES lane, disable
the IRQ, then free it.
This patch removes these operations in favor of generic functions.
Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 96 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.h | 2 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 142 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.h | 4 |
4 files changed, 69 insertions, 175 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index c2061e20bb32..30365a54c31b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -2054,6 +2054,71 @@ 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 | { |
@@ -2069,12 +2134,11 @@ static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port, | |||
2069 | if (err) | 2134 | if (err) |
2070 | return err; | 2135 | return err; |
2071 | 2136 | ||
2072 | if (chip->info->ops->serdes_irq_setup) | 2137 | err = mv88e6xxx_serdes_irq_request(chip, port, lane); |
2073 | err = chip->info->ops->serdes_irq_setup(chip, port); | ||
2074 | } else { | 2138 | } else { |
2075 | if (chip->info->ops->serdes_irq_free && | 2139 | err = mv88e6xxx_serdes_irq_free(chip, port, lane); |
2076 | chip->ports[port].serdes_irq) | 2140 | if (err) |
2077 | chip->info->ops->serdes_irq_free(chip, port); | 2141 | return err; |
2078 | 2142 | ||
2079 | err = mv88e6xxx_serdes_power_down(chip, port, lane); | 2143 | err = mv88e6xxx_serdes_power_down(chip, port, lane); |
2080 | } | 2144 | } |
@@ -2936,8 +3000,6 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { | |||
2936 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3000 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
2937 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3001 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
2938 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3002 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
2939 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
2940 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
2941 | .gpio_ops = &mv88e6352_gpio_ops, | 3003 | .gpio_ops = &mv88e6352_gpio_ops, |
2942 | .phylink_validate = mv88e6341_phylink_validate, | 3004 | .phylink_validate = mv88e6341_phylink_validate, |
2943 | }; | 3005 | }; |
@@ -3188,8 +3250,6 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { | |||
3188 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, | 3250 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, |
3189 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, | 3251 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, |
3190 | .serdes_irq_status = mv88e6352_serdes_irq_status, | 3252 | .serdes_irq_status = mv88e6352_serdes_irq_status, |
3191 | .serdes_irq_setup = mv88e6352_serdes_irq_setup, | ||
3192 | .serdes_irq_free = mv88e6352_serdes_irq_free, | ||
3193 | .gpio_ops = &mv88e6352_gpio_ops, | 3253 | .gpio_ops = &mv88e6352_gpio_ops, |
3194 | .phylink_validate = mv88e6352_phylink_validate, | 3254 | .phylink_validate = mv88e6352_phylink_validate, |
3195 | }; | 3255 | }; |
@@ -3274,8 +3334,6 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { | |||
3274 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3334 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3275 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3335 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3276 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3336 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3277 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3278 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3279 | .gpio_ops = &mv88e6352_gpio_ops, | 3337 | .gpio_ops = &mv88e6352_gpio_ops, |
3280 | .phylink_validate = mv88e6390_phylink_validate, | 3338 | .phylink_validate = mv88e6390_phylink_validate, |
3281 | }; | 3339 | }; |
@@ -3324,8 +3382,6 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { | |||
3324 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3382 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3325 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3383 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3326 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3384 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3327 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3328 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3329 | .gpio_ops = &mv88e6352_gpio_ops, | 3385 | .gpio_ops = &mv88e6352_gpio_ops, |
3330 | .phylink_validate = mv88e6390x_phylink_validate, | 3386 | .phylink_validate = mv88e6390x_phylink_validate, |
3331 | }; | 3387 | }; |
@@ -3374,8 +3430,6 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { | |||
3374 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3430 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3375 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3431 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3376 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3432 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3377 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3378 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3379 | .avb_ops = &mv88e6390_avb_ops, | 3433 | .avb_ops = &mv88e6390_avb_ops, |
3380 | .ptp_ops = &mv88e6352_ptp_ops, | 3434 | .ptp_ops = &mv88e6352_ptp_ops, |
3381 | .phylink_validate = mv88e6390_phylink_validate, | 3435 | .phylink_validate = mv88e6390_phylink_validate, |
@@ -3426,8 +3480,6 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { | |||
3426 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, | 3480 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, |
3427 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, | 3481 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, |
3428 | .serdes_irq_status = mv88e6352_serdes_irq_status, | 3482 | .serdes_irq_status = mv88e6352_serdes_irq_status, |
3429 | .serdes_irq_setup = mv88e6352_serdes_irq_setup, | ||
3430 | .serdes_irq_free = mv88e6352_serdes_irq_free, | ||
3431 | .gpio_ops = &mv88e6352_gpio_ops, | 3483 | .gpio_ops = &mv88e6352_gpio_ops, |
3432 | .avb_ops = &mv88e6352_avb_ops, | 3484 | .avb_ops = &mv88e6352_avb_ops, |
3433 | .ptp_ops = &mv88e6352_ptp_ops, | 3485 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3518,8 +3570,6 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { | |||
3518 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3570 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3519 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3571 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3520 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3572 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3521 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3522 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3523 | .gpio_ops = &mv88e6352_gpio_ops, | 3573 | .gpio_ops = &mv88e6352_gpio_ops, |
3524 | .avb_ops = &mv88e6390_avb_ops, | 3574 | .avb_ops = &mv88e6390_avb_ops, |
3525 | .ptp_ops = &mv88e6352_ptp_ops, | 3575 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3658,8 +3708,6 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { | |||
3658 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3708 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3659 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3709 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3660 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3710 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3661 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3662 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3663 | .gpio_ops = &mv88e6352_gpio_ops, | 3711 | .gpio_ops = &mv88e6352_gpio_ops, |
3664 | .avb_ops = &mv88e6390_avb_ops, | 3712 | .avb_ops = &mv88e6390_avb_ops, |
3665 | .ptp_ops = &mv88e6352_ptp_ops, | 3713 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3793,8 +3841,6 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { | |||
3793 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, | 3841 | .serdes_irq_mapping = mv88e6352_serdes_irq_mapping, |
3794 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, | 3842 | .serdes_irq_enable = mv88e6352_serdes_irq_enable, |
3795 | .serdes_irq_status = mv88e6352_serdes_irq_status, | 3843 | .serdes_irq_status = mv88e6352_serdes_irq_status, |
3796 | .serdes_irq_setup = mv88e6352_serdes_irq_setup, | ||
3797 | .serdes_irq_free = mv88e6352_serdes_irq_free, | ||
3798 | .gpio_ops = &mv88e6352_gpio_ops, | 3844 | .gpio_ops = &mv88e6352_gpio_ops, |
3799 | .avb_ops = &mv88e6352_avb_ops, | 3845 | .avb_ops = &mv88e6352_avb_ops, |
3800 | .ptp_ops = &mv88e6352_ptp_ops, | 3846 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3850,8 +3896,6 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { | |||
3850 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3896 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3851 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3897 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3852 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3898 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3853 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3854 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3855 | .gpio_ops = &mv88e6352_gpio_ops, | 3899 | .gpio_ops = &mv88e6352_gpio_ops, |
3856 | .avb_ops = &mv88e6390_avb_ops, | 3900 | .avb_ops = &mv88e6390_avb_ops, |
3857 | .ptp_ops = &mv88e6352_ptp_ops, | 3901 | .ptp_ops = &mv88e6352_ptp_ops, |
@@ -3904,8 +3948,6 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { | |||
3904 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, | 3948 | .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, |
3905 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, | 3949 | .serdes_irq_enable = mv88e6390_serdes_irq_enable, |
3906 | .serdes_irq_status = mv88e6390_serdes_irq_status, | 3950 | .serdes_irq_status = mv88e6390_serdes_irq_status, |
3907 | .serdes_irq_setup = mv88e6390_serdes_irq_setup, | ||
3908 | .serdes_irq_free = mv88e6390_serdes_irq_free, | ||
3909 | .gpio_ops = &mv88e6352_gpio_ops, | 3951 | .gpio_ops = &mv88e6352_gpio_ops, |
3910 | .avb_ops = &mv88e6390_avb_ops, | 3952 | .avb_ops = &mv88e6390_avb_ops, |
3911 | .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 9a73fd1d643b..6bc0a4e4fe7b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h | |||
@@ -450,8 +450,6 @@ struct mv88e6xxx_ops { | |||
450 | /* SERDES interrupt handling */ | 450 | /* SERDES interrupt handling */ |
451 | unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip, | 451 | unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip, |
452 | int port); | 452 | int port); |
453 | int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port); | ||
454 | void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port); | ||
455 | int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane, | 453 | int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane, |
456 | bool enable); | 454 | bool enable); |
457 | irqreturn_t (*serdes_irq_status)(struct mv88e6xxx_chip *chip, int port, | 455 | irqreturn_t (*serdes_irq_status)(struct mv88e6xxx_chip *chip, int port, |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index d37419ba26ab..902feb398746 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c | |||
@@ -221,19 +221,6 @@ irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, | |||
221 | return ret; | 221 | return ret; |
222 | } | 222 | } |
223 | 223 | ||
224 | static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id) | ||
225 | { | ||
226 | struct mv88e6xxx_port *port = dev_id; | ||
227 | struct mv88e6xxx_chip *chip = port->chip; | ||
228 | irqreturn_t ret = IRQ_NONE; | ||
229 | |||
230 | mv88e6xxx_reg_lock(chip); | ||
231 | ret = mv88e6xxx_serdes_irq_status(chip, port->port, 0); | ||
232 | mv88e6xxx_reg_unlock(chip); | ||
233 | |||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, | 224 | int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, |
238 | bool enable) | 225 | bool enable) |
239 | { | 226 | { |
@@ -250,61 +237,6 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) | |||
250 | return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); | 237 | return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); |
251 | } | 238 | } |
252 | 239 | ||
253 | int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) | ||
254 | { | ||
255 | unsigned int irq; | ||
256 | u8 lane; | ||
257 | int err; | ||
258 | |||
259 | lane = mv88e6xxx_serdes_get_lane(chip, port); | ||
260 | if (!lane) | ||
261 | return 0; | ||
262 | |||
263 | irq = mv88e6xxx_serdes_irq_mapping(chip, port); | ||
264 | if (!irq) | ||
265 | return 0; | ||
266 | |||
267 | chip->ports[port].serdes_irq = irq; | ||
268 | |||
269 | /* Requesting the IRQ will trigger irq callbacks. So we cannot | ||
270 | * hold the reg_lock. | ||
271 | */ | ||
272 | mv88e6xxx_reg_unlock(chip); | ||
273 | err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, | ||
274 | mv88e6352_serdes_thread_fn, | ||
275 | IRQF_ONESHOT, "mv88e6xxx-serdes", | ||
276 | &chip->ports[port]); | ||
277 | mv88e6xxx_reg_lock(chip); | ||
278 | |||
279 | if (err) { | ||
280 | dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", | ||
281 | err); | ||
282 | return err; | ||
283 | } | ||
284 | |||
285 | return mv88e6xxx_serdes_irq_enable(chip, port, lane); | ||
286 | } | ||
287 | |||
288 | void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) | ||
289 | { | ||
290 | u8 lane; | ||
291 | |||
292 | lane = mv88e6xxx_serdes_get_lane(chip, port); | ||
293 | if (!lane) | ||
294 | return; | ||
295 | |||
296 | mv88e6xxx_serdes_irq_disable(chip, port, lane); | ||
297 | |||
298 | /* Freeing the IRQ will trigger irq callbacks. So we cannot | ||
299 | * hold the reg_lock. | ||
300 | */ | ||
301 | mv88e6xxx_reg_unlock(chip); | ||
302 | free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); | ||
303 | mv88e6xxx_reg_lock(chip); | ||
304 | |||
305 | chip->ports[port].serdes_irq = 0; | ||
306 | } | ||
307 | |||
308 | u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) | 240 | u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
309 | { | 241 | { |
310 | u8 cmode = chip->ports[port].cmode; | 242 | u8 cmode = chip->ports[port].cmode; |
@@ -622,81 +554,7 @@ irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, | |||
622 | return ret; | 554 | return ret; |
623 | } | 555 | } |
624 | 556 | ||
625 | static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) | ||
626 | { | ||
627 | struct mv88e6xxx_port *port = dev_id; | ||
628 | struct mv88e6xxx_chip *chip = port->chip; | ||
629 | irqreturn_t ret = IRQ_NONE; | ||
630 | u8 lane; | ||
631 | |||
632 | mv88e6xxx_reg_lock(chip); | ||
633 | lane = mv88e6xxx_serdes_get_lane(chip, port->port); | ||
634 | if (!lane) | ||
635 | goto out; | ||
636 | |||
637 | ret = mv88e6xxx_serdes_irq_status(chip, port->port, lane); | ||
638 | out: | ||
639 | mv88e6xxx_reg_unlock(chip); | ||
640 | |||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) | 557 | unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) |
645 | { | 558 | { |
646 | return irq_find_mapping(chip->g2_irq.domain, port); | 559 | return irq_find_mapping(chip->g2_irq.domain, port); |
647 | } | 560 | } |
648 | |||
649 | int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) | ||
650 | { | ||
651 | unsigned int irq; | ||
652 | int err; | ||
653 | u8 lane; | ||
654 | |||
655 | lane = mv88e6xxx_serdes_get_lane(chip, port); | ||
656 | if (!lane) | ||
657 | return 0; | ||
658 | |||
659 | irq = mv88e6xxx_serdes_irq_mapping(chip, port); | ||
660 | if (!irq) | ||
661 | return 0; | ||
662 | |||
663 | chip->ports[port].serdes_irq = irq; | ||
664 | |||
665 | /* Requesting the IRQ will trigger irq callbacks. So we cannot | ||
666 | * hold the reg_lock. | ||
667 | */ | ||
668 | mv88e6xxx_reg_unlock(chip); | ||
669 | err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, | ||
670 | mv88e6390_serdes_thread_fn, | ||
671 | IRQF_ONESHOT, "mv88e6xxx-serdes", | ||
672 | &chip->ports[port]); | ||
673 | mv88e6xxx_reg_lock(chip); | ||
674 | |||
675 | if (err) { | ||
676 | dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", | ||
677 | err); | ||
678 | return err; | ||
679 | } | ||
680 | |||
681 | return mv88e6xxx_serdes_irq_enable(chip, port, lane); | ||
682 | } | ||
683 | |||
684 | void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) | ||
685 | { | ||
686 | u8 lane; | ||
687 | |||
688 | lane = mv88e6xxx_serdes_get_lane(chip, port); | ||
689 | if (!lane) | ||
690 | return; | ||
691 | |||
692 | mv88e6xxx_serdes_irq_disable(chip, port, lane); | ||
693 | |||
694 | /* Freeing the IRQ will trigger irq callbacks. So we cannot | ||
695 | * hold the reg_lock. | ||
696 | */ | ||
697 | mv88e6xxx_reg_unlock(chip); | ||
698 | free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); | ||
699 | mv88e6xxx_reg_lock(chip); | ||
700 | |||
701 | chip->ports[port].serdes_irq = 0; | ||
702 | } | ||
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 52f937347a36..bd8df36ab537 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h | |||
@@ -86,8 +86,6 @@ int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, | |||
86 | bool on); | 86 | bool on); |
87 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, | 87 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, |
88 | bool on); | 88 | bool on); |
89 | int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port); | ||
90 | void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port); | ||
91 | int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, | 89 | int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, |
92 | bool enable); | 90 | bool enable); |
93 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, | 91 | int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, |
@@ -101,8 +99,6 @@ int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, | |||
101 | int port, uint8_t *data); | 99 | int port, uint8_t *data); |
102 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | 100 | int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, |
103 | uint64_t *data); | 101 | uint64_t *data); |
104 | int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port); | ||
105 | void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port); | ||
106 | 102 | ||
107 | /* Return the (first) SERDES lane address a port is using, 0 otherwise. */ | 103 | /* Return the (first) SERDES lane address a port is using, 0 otherwise. */ |
108 | static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, | 104 | static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip, |