]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/cxgb3-commnonize-LASI-phy-code
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / cxgb3-commnonize-LASI-phy-code
CommitLineData
2cb7cef9
BS
1Commit-Id: 9b1e36566c5fafbcc732c971acfcf8580332931a
2From: Divy Le Ray <divy@chelsio.com>
3Date: Wed, 8 Oct 2008 17:39:31 -0700
4Acked-by: Karsten Keil <kkeil@novell.com>
5Subject: [PATCH] cxgb3: commnonize LASI phy code
6Reference: bnc#446739
7
8Add generic code to manage interrupt driven PHYs.
9Do not reset the phy after link parameters update,
10the new values might get lost.
11Return early from link change notification
12when the link parameters remain unchanged.
13
14Signed-off-by: Divy Le Ray <divy@chelsio.com>
15Signed-off-by: David S. Miller <davem@davemloft.net>
16
17Index: linux-2.6.27/drivers/net/cxgb3/ael1002.c
18===================================================================
19--- linux-2.6.27.orig/drivers/net/cxgb3/ael1002.c
20+++ linux-2.6.27/drivers/net/cxgb3/ael1002.c
21@@ -39,9 +39,6 @@ enum {
22 AEL1002_PWR_DOWN_LO = 0xc012,
23 AEL1002_XFI_EQL = 0xc015,
24 AEL1002_LB_EN = 0xc017,
25-
26- LASI_CTRL = 0x9002,
27- LASI_STAT = 0x9005
28 };
29
30 static void ael100x_txon(struct cphy *phy)
31@@ -134,33 +131,6 @@ static int ael1006_reset(struct cphy *ph
32 return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
33 }
34
35-static int ael1006_intr_enable(struct cphy *phy)
36-{
37- return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
38-}
39-
40-static int ael1006_intr_disable(struct cphy *phy)
41-{
42- return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
43-}
44-
45-static int ael1006_intr_clear(struct cphy *phy)
46-{
47- u32 val;
48-
49- return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
50-}
51-
52-static int ael1006_intr_handler(struct cphy *phy)
53-{
54- unsigned int status;
55- int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
56-
57- if (err)
58- return err;
59- return (status & 1) ? cphy_cause_link_change : 0;
60-}
61-
62 static int ael1006_power_down(struct cphy *phy, int enable)
63 {
64 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
65@@ -169,10 +139,10 @@ static int ael1006_power_down(struct cph
66
67 static struct cphy_ops ael1006_ops = {
68 .reset = ael1006_reset,
69- .intr_enable = ael1006_intr_enable,
70- .intr_disable = ael1006_intr_disable,
71- .intr_clear = ael1006_intr_clear,
72- .intr_handler = ael1006_intr_handler,
73+ .intr_enable = t3_phy_lasi_intr_enable,
74+ .intr_disable = t3_phy_lasi_intr_disable,
75+ .intr_clear = t3_phy_lasi_intr_clear,
76+ .intr_handler = t3_phy_lasi_intr_handler,
77 .get_link_status = ael100x_get_link_status,
78 .power_down = ael1006_power_down,
79 };
80@@ -189,10 +159,10 @@ int t3_ael1006_phy_prep(struct cphy *phy
81
82 static struct cphy_ops qt2045_ops = {
83 .reset = ael1006_reset,
84- .intr_enable = ael1006_intr_enable,
85- .intr_disable = ael1006_intr_disable,
86- .intr_clear = ael1006_intr_clear,
87- .intr_handler = ael1006_intr_handler,
88+ .intr_enable = t3_phy_lasi_intr_enable,
89+ .intr_disable = t3_phy_lasi_intr_disable,
90+ .intr_clear = t3_phy_lasi_intr_clear,
91+ .intr_handler = t3_phy_lasi_intr_handler,
92 .get_link_status = ael100x_get_link_status,
93 .power_down = ael1006_power_down,
94 };
95Index: linux-2.6.27/drivers/net/cxgb3/common.h
96===================================================================
97--- linux-2.6.27.orig/drivers/net/cxgb3/common.h
98+++ linux-2.6.27/drivers/net/cxgb3/common.h
99@@ -522,7 +522,20 @@ enum {
100 MDIO_DEV_PMA_PMD = 1,
101 MDIO_DEV_WIS = 2,
102 MDIO_DEV_PCS = 3,
103- MDIO_DEV_XGXS = 4
104+ MDIO_DEV_XGXS = 4,
105+ MDIO_DEV_ANEG = 7,
106+ MDIO_DEV_VEND1 = 30,
107+ MDIO_DEV_VEND2 = 31
108+};
109+
110+/* LASI control and status registers */
111+enum {
112+ RX_ALARM_CTRL = 0x9000,
113+ TX_ALARM_CTRL = 0x9001,
114+ LASI_CTRL = 0x9002,
115+ RX_ALARM_STAT = 0x9003,
116+ TX_ALARM_STAT = 0x9004,
117+ LASI_STAT = 0x9005
118 };
119
120 /* PHY loopback direction */
121@@ -665,6 +678,10 @@ int t3_mdio_change_bits(struct cphy *phy
122 int t3_phy_reset(struct cphy *phy, int mmd, int wait);
123 int t3_phy_advertise(struct cphy *phy, unsigned int advert);
124 int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex);
125+int t3_phy_lasi_intr_enable(struct cphy *phy);
126+int t3_phy_lasi_intr_disable(struct cphy *phy);
127+int t3_phy_lasi_intr_clear(struct cphy *phy);
128+int t3_phy_lasi_intr_handler(struct cphy *phy);
129
130 void t3_intr_enable(struct adapter *adapter);
131 void t3_intr_disable(struct adapter *adapter);
132Index: linux-2.6.27/drivers/net/cxgb3/cxgb3_main.c
133===================================================================
134--- linux-2.6.27.orig/drivers/net/cxgb3/cxgb3_main.c
135+++ linux-2.6.27/drivers/net/cxgb3/cxgb3_main.c
136@@ -1586,11 +1586,22 @@ static int speed_duplex_to_caps(int spee
137
138 static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
139 {
140+ int cap;
141 struct port_info *p = netdev_priv(dev);
142 struct link_config *lc = &p->link_config;
143
144- if (!(lc->supported & SUPPORTED_Autoneg))
145- return -EOPNOTSUPP; /* can't change speed/duplex */
146+ if (!(lc->supported & SUPPORTED_Autoneg)) {
147+ /*
148+ * PHY offers a single speed/duplex. See if that's what's
149+ * being requested.
150+ */
151+ if (cmd->autoneg == AUTONEG_DISABLE) {
152+ cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
153+ if (lc->supported & cap)
154+ return 0;
155+ }
156+ return -EINVAL;
157+ }
158
159 if (cmd->autoneg == AUTONEG_DISABLE) {
160 int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
161@@ -2281,7 +2292,7 @@ static int cxgb_ioctl(struct net_device
162 mmd = data->phy_id >> 8;
163 if (!mmd)
164 mmd = MDIO_DEV_PCS;
165- else if (mmd > MDIO_DEV_XGXS)
166+ else if (mmd > MDIO_DEV_VEND2)
167 return -EINVAL;
168
169 ret =
170@@ -2307,7 +2318,7 @@ static int cxgb_ioctl(struct net_device
171 mmd = data->phy_id >> 8;
172 if (!mmd)
173 mmd = MDIO_DEV_PCS;
174- else if (mmd > MDIO_DEV_XGXS)
175+ else if (mmd > MDIO_DEV_VEND2)
176 return -EINVAL;
177
178 ret =
179Index: linux-2.6.27/drivers/net/cxgb3/t3_hw.c
180===================================================================
181--- linux-2.6.27.orig/drivers/net/cxgb3/t3_hw.c
182+++ linux-2.6.27/drivers/net/cxgb3/t3_hw.c
183@@ -442,6 +442,33 @@ int t3_set_phy_speed_duplex(struct cphy
184 return mdio_write(phy, 0, MII_BMCR, ctl);
185 }
186
187+int t3_phy_lasi_intr_enable(struct cphy *phy)
188+{
189+ return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
190+}
191+
192+int t3_phy_lasi_intr_disable(struct cphy *phy)
193+{
194+ return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
195+}
196+
197+int t3_phy_lasi_intr_clear(struct cphy *phy)
198+{
199+ u32 val;
200+
201+ return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
202+}
203+
204+int t3_phy_lasi_intr_handler(struct cphy *phy)
205+{
206+ unsigned int status;
207+ int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
208+
209+ if (err)
210+ return err;
211+ return (status & 1) ? cphy_cause_link_change : 0;
212+}
213+
214 static const struct adapter_info t3_adap_info[] = {
215 {2, 0,
216 F_GPIO2_OEN | F_GPIO4_OEN |
217@@ -1132,6 +1159,15 @@ void t3_link_changed(struct adapter *ada
218
219 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
220
221+ if (lc->requested_fc & PAUSE_AUTONEG)
222+ fc &= lc->requested_fc;
223+ else
224+ fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
225+
226+ if (link_ok == lc->link_ok && speed == lc->speed &&
227+ duplex == lc->duplex && fc == lc->fc)
228+ return; /* nothing changed */
229+
230 if (link_ok != lc->link_ok && adapter->params.rev > 0 &&
231 uses_xaui(adapter)) {
232 if (link_ok)
233@@ -1142,10 +1178,6 @@ void t3_link_changed(struct adapter *ada
234 lc->link_ok = link_ok;
235 lc->speed = speed < 0 ? SPEED_INVALID : speed;
236 lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
237- if (lc->requested_fc & PAUSE_AUTONEG)
238- fc &= lc->requested_fc;
239- else
240- fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
241
242 if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
243 /* Set MAC speed, duplex, and flow control to match PHY. */
244@@ -1191,7 +1223,6 @@ int t3_link_start(struct cphy *phy, stru
245 fc);
246 /* Also disables autoneg */
247 phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
248- phy->ops->reset(phy, 0);
249 } else
250 phy->ops->autoneg_enable(phy);
251 } else {