| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001 | 
|  | 2 | From: Jonas Gorski <jogo@openwrt.org> | 
|  | 3 | Date: Tue, 16 Jun 2015 13:15:08 +0200 | 
|  | 4 | Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command | 
|  | 5 |  | 
|  | 6 | It seems some phys have some maximum timings for accessing the MDIO line, | 
|  | 7 | resulting in bit errors under cpu stress. Prevent this from happening by | 
|  | 8 | disabling interrupts when sending commands. | 
|  | 9 |  | 
|  | 10 | Signed-off-by: Jonas Gorski <jogo@openwrt.org> | 
|  | 11 | --- | 
|  | 12 | drivers/net/phy/mdio-bitbang.c | 9 +++++++++ | 
|  | 13 | 1 file changed, 9 insertions(+) | 
|  | 14 |  | 
|  | 15 | --- a/drivers/net/phy/mdio-bitbang.c | 
|  | 16 | +++ b/drivers/net/phy/mdio-bitbang.c | 
|  | 17 | @@ -14,6 +14,7 @@ | 
|  | 18 | * Vitaly Bordug <vbordug@ru.mvista.com> | 
|  | 19 | */ | 
|  | 20 |  | 
|  | 21 | +#include <linux/irqflags.h> | 
|  | 22 | #include <linux/module.h> | 
|  | 23 | #include <linux/mdio-bitbang.h> | 
|  | 24 | #include <linux/types.h> | 
|  | 25 | @@ -153,7 +154,9 @@ static int mdiobb_read(struct mii_bus *b | 
|  | 26 | { | 
|  | 27 | struct mdiobb_ctrl *ctrl = bus->priv; | 
|  | 28 | int ret; | 
|  | 29 | +	unsigned long flags; | 
|  | 30 |  | 
|  | 31 | +	local_irq_save(flags); | 
|  | 32 | if (reg & MII_ADDR_C45) { | 
|  | 33 | reg = mdiobb_cmd_addr(ctrl, phy, reg); | 
|  | 34 | mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); | 
|  | 35 | @@ -166,13 +169,17 @@ static int mdiobb_read(struct mii_bus *b | 
|  | 36 |  | 
|  | 37 | ret = mdiobb_get_num(ctrl, 16); | 
|  | 38 | mdiobb_get_bit(ctrl); | 
|  | 39 | +	local_irq_restore(flags); | 
|  | 40 | + | 
|  | 41 | return ret; | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) | 
|  | 45 | { | 
|  | 46 | struct mdiobb_ctrl *ctrl = bus->priv; | 
|  | 47 | +	unsigned long flags; | 
|  | 48 |  | 
|  | 49 | +	local_irq_save(flags); | 
|  | 50 | if (reg & MII_ADDR_C45) { | 
|  | 51 | reg = mdiobb_cmd_addr(ctrl, phy, reg); | 
|  | 52 | mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); | 
|  | 53 | @@ -187,6 +194,8 @@ static int mdiobb_write(struct mii_bus * | 
|  | 54 |  | 
|  | 55 | ctrl->ops->set_mdio_dir(ctrl, 0); | 
|  | 56 | mdiobb_get_bit(ctrl); | 
|  | 57 | +	local_irq_restore(flags); | 
|  | 58 | + | 
|  | 59 | return 0; | 
|  | 60 | } | 
|  | 61 |  |