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
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.
14 Signed-off-by: Divy Le Ray <divy@chelsio.com>
15 Signed-off-by: David S. Miller <davem@davemloft.net>
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,
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);
35 -static int ael1006_intr_enable(struct cphy *phy)
37 - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
40 -static int ael1006_intr_disable(struct cphy *phy)
42 - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
45 -static int ael1006_intr_clear(struct cphy *phy)
49 - return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
52 -static int ael1006_intr_handler(struct cphy *phy)
54 - unsigned int status;
55 - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
59 - return (status & 1) ? cphy_cause_link_change : 0;
62 static int ael1006_power_down(struct cphy *phy, int enable)
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
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,
80 @@ -189,10 +159,10 @@ int t3_ael1006_phy_prep(struct cphy *phy
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,
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,
106 + MDIO_DEV_VEND1 = 30,
107 + MDIO_DEV_VEND2 = 31
110 +/* LASI control and status registers */
112 + RX_ALARM_CTRL = 0x9000,
113 + TX_ALARM_CTRL = 0x9001,
114 + LASI_CTRL = 0x9002,
115 + RX_ALARM_STAT = 0x9003,
116 + TX_ALARM_STAT = 0x9004,
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);
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
138 static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
141 struct port_info *p = netdev_priv(dev);
142 struct link_config *lc = &p->link_config;
144 - if (!(lc->supported & SUPPORTED_Autoneg))
145 - return -EOPNOTSUPP; /* can't change speed/duplex */
146 + if (!(lc->supported & SUPPORTED_Autoneg)) {
148 + * PHY offers a single speed/duplex. See if that's what's
151 + if (cmd->autoneg == AUTONEG_DISABLE) {
152 + cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
153 + if (lc->supported & cap)
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;
165 - else if (mmd > MDIO_DEV_XGXS)
166 + else if (mmd > MDIO_DEV_VEND2)
170 @@ -2307,7 +2318,7 @@ static int cxgb_ioctl(struct net_device
171 mmd = data->phy_id >> 8;
174 - else if (mmd > MDIO_DEV_XGXS)
175 + else if (mmd > MDIO_DEV_VEND2)
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);
187 +int t3_phy_lasi_intr_enable(struct cphy *phy)
189 + return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
192 +int t3_phy_lasi_intr_disable(struct cphy *phy)
194 + return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
197 +int t3_phy_lasi_intr_clear(struct cphy *phy)
201 + return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
204 +int t3_phy_lasi_intr_handler(struct cphy *phy)
206 + unsigned int status;
207 + int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
211 + return (status & 1) ? cphy_cause_link_change : 0;
214 static const struct adapter_info t3_adap_info[] = {
216 F_GPIO2_OEN | F_GPIO4_OEN |
217 @@ -1132,6 +1159,15 @@ void t3_link_changed(struct adapter *ada
219 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
221 + if (lc->requested_fc & PAUSE_AUTONEG)
222 + fc &= lc->requested_fc;
224 + fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
226 + if (link_ok == lc->link_ok && speed == lc->speed &&
227 + duplex == lc->duplex && fc == lc->fc)
228 + return; /* nothing changed */
230 if (link_ok != lc->link_ok && adapter->params.rev > 0 &&
231 uses_xaui(adapter)) {
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;
240 - fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
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
246 /* Also disables autoneg */
247 phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
248 - phy->ops->reset(phy, 0);
250 phy->ops->autoneg_enable(phy);