aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ar71xx/patches-4.9/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch
blob: a830346a31ef5b54f00ca3a490879981fb0d7b73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Tue, 16 Jun 2015 13:15:08 +0200
Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command

It seems some phys have some maximum timings for accessing the MDIO line,
resulting in bit errors under cpu stress. Prevent this from happening by
disabling interrupts when sending commands.

Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
 drivers/net/phy/mdio-bitbang.c | 9 +++++++++
 1 file changed, 9 insertions(+)

--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -17,6 +17,7 @@
  * kind, whether express or implied.
  */
 
+#include <linux/irqflags.h>
 #include <linux/module.h>
 #include <linux/mdio-bitbang.h>
 #include <linux/types.h>
@@ -156,7 +157,9 @@ static int mdiobb_read(struct mii_bus *b
 {
 	struct mdiobb_ctrl *ctrl = bus->priv;
 	int ret;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	if (reg & MII_ADDR_C45) {
 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
 		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
@@ -169,13 +172,17 @@ static int mdiobb_read(struct mii_bus *b
 
 	ret = mdiobb_get_num(ctrl, 16);
 	mdiobb_get_bit(ctrl);
+	local_irq_restore(flags);
+
 	return ret;
 }
 
 static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
 {
 	struct mdiobb_ctrl *ctrl = bus->priv;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	if (reg & MII_ADDR_C45) {
 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
 		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
@@ -190,6 +197,8 @@ static int mdiobb_write(struct mii_bus *
 
 	ctrl->ops->set_mdio_dir(ctrl, 0);
 	mdiobb_get_bit(ctrl);
+	local_irq_restore(flags);
+
 	return 0;
 }
 
BSG Vendor specific definations */ #define A84_ISSUE_WRITE_TYPE_CMD 0 #define A84_ISSUE_READ_TYPE_CMD 1 #define A84_CLEANUP_CMD 2 #define A84_ISSUE_RESET_OP_FW 3 #define A84_ISSUE_RESET_DIAG_FW 4 #define A84_ISSUE_UPDATE_OPFW_CMD 5 #define A84_ISSUE_UPDATE_DIAGFW_CMD 6 struct qla84_mgmt_param { union { struct { uint32_t start_addr; } mem; /* for QLA84_MGMT_READ/WRITE_MEM */ struct { uint32_t id; #define QLA84_MGMT_CONFIG_ID_UIF 1 #define QLA84_MGMT_CONFIG_ID_FCOE_COS 2 #define QLA84_MGMT_CONFIG_ID_PAUSE 3 #define QLA84_MGMT_CONFIG_ID_TIMEOUTS 4 uint32_t param0; uint32_t param1; } config; /* for QLA84_MGMT_CHNG_CONFIG */ struct { uint32_t type; #define QLA84_MGMT_INFO_CONFIG_LOG_DATA 1 /* Get Config Log Data */ #define QLA84_MGMT_INFO_LOG_DATA 2 /* Get Log Data */ #define QLA84_MGMT_INFO_PORT_STAT 3 /* Get Port Statistics */ #define QLA84_MGMT_INFO_LIF_STAT 4 /* Get LIF Statistics */ #define QLA84_MGMT_INFO_ASIC_STAT 5 /* Get ASIC Statistics */ #define QLA84_MGMT_INFO_CONFIG_PARAMS 6 /* Get Config Parameters */ #define QLA84_MGMT_INFO_PANIC_LOG 7 /* Get Panic Log */ uint32_t context; /* * context definitions for QLA84_MGMT_INFO_CONFIG_LOG_DATA */ #define IC_LOG_DATA_LOG_ID_DEBUG_LOG 0 #define IC_LOG_DATA_LOG_ID_LEARN_LOG 1 #define IC_LOG_DATA_LOG_ID_FC_ACL_INGRESS_LOG 2 #define IC_LOG_DATA_LOG_ID_FC_ACL_EGRESS_LOG 3 #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_INGRESS_LOG 4 #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_EGRESS_LOG 5 #define IC_LOG_DATA_LOG_ID_MESSAGE_TRANSMIT_LOG 6 #define IC_LOG_DATA_LOG_ID_MESSAGE_RECEIVE_LOG 7 #define IC_LOG_DATA_LOG_ID_LINK_EVENT_LOG 8 #define IC_LOG_DATA_LOG_ID_DCX_LOG 9 /* * context definitions for QLA84_MGMT_INFO_PORT_STAT */ #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT0 0 #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT1 1 #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT0 2 #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT1 3 #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT0 4 #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT1 5 /* * context definitions for QLA84_MGMT_INFO_LIF_STAT */ #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT0 0 #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT1 1 #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT0 2 #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT1 3 #define IC_LIF_STATISTICS_LIF_NUMBER_CPU 6 } info; /* for QLA84_MGMT_GET_INFO */ } u; }; struct qla84_msg_mgmt { uint16_t cmd; #define QLA84_MGMT_READ_MEM 0x00 #define QLA84_MGMT_WRITE_MEM 0x01 #define QLA84_MGMT_CHNG_CONFIG 0x02 #define QLA84_MGMT_GET_INFO 0x03 uint16_t rsrvd; struct qla84_mgmt_param mgmtp;/* parameters for cmd */ uint32_t len; /* bytes in payload following this struct */ uint8_t payload[0]; /* payload for cmd */ }; struct qla_bsg_a84_mgmt { struct qla84_msg_mgmt mgmt; } __attribute__ ((packed)); struct qla_scsi_addr { uint16_t bus; uint16_t target; } __attribute__ ((packed)); struct qla_ext_dest_addr { union { uint8_t wwnn[8]; uint8_t wwpn[8]; uint8_t id[4]; struct qla_scsi_addr scsi_addr; } dest_addr; uint16_t dest_type; #define EXT_DEF_TYPE_WWPN 2 uint16_t lun; uint16_t padding[2]; } __attribute__ ((packed)); struct qla_port_param { struct qla_ext_dest_addr fc_scsi_addr; uint16_t mode; uint16_t speed; } __attribute__ ((packed)); #endif