]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Commit-Id: 9b1e36566c5fafbcc732c971acfcf8580332931a |
2 | From: Divy Le Ray <divy@chelsio.com> | |
3 | Date: Wed, 8 Oct 2008 17:39:31 -0700 | |
4 | Acked-by: Karsten Keil <kkeil@novell.com> | |
5 | Subject: [PATCH] cxgb3: commnonize LASI phy code | |
6 | Reference: bnc#446739 | |
7 | ||
8 | Add generic code to manage interrupt driven PHYs. | |
9 | Do not reset the phy after link parameters update, | |
10 | the new values might get lost. | |
11 | Return early from link change notification | |
12 | when the link parameters remain unchanged. | |
13 | ||
14 | Signed-off-by: Divy Le Ray <divy@chelsio.com> | |
15 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
16 | ||
17 | Index: 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 | }; | |
95 | Index: 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); | |
132 | Index: 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 = | |
179 | Index: 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 { |