aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/cxgb3/ael1002.c46
-rw-r--r--drivers/net/cxgb3/common.h19
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c19
-rw-r--r--drivers/net/cxgb3/t3_hw.c41
4 files changed, 77 insertions, 48 deletions
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c
index f4e046e32fc6..f6e575fa7468 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/cxgb3/ael1002.c
@@ -39,9 +39,6 @@ enum {
39 AEL1002_PWR_DOWN_LO = 0xc012, 39 AEL1002_PWR_DOWN_LO = 0xc012,
40 AEL1002_XFI_EQL = 0xc015, 40 AEL1002_XFI_EQL = 0xc015,
41 AEL1002_LB_EN = 0xc017, 41 AEL1002_LB_EN = 0xc017,
42
43 LASI_CTRL = 0x9002,
44 LASI_STAT = 0x9005
45}; 42};
46 43
47static void ael100x_txon(struct cphy *phy) 44static void ael100x_txon(struct cphy *phy)
@@ -134,33 +131,6 @@ static int ael1006_reset(struct cphy *phy, int wait)
134 return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 131 return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
135} 132}
136 133
137static int ael1006_intr_enable(struct cphy *phy)
138{
139 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
140}
141
142static int ael1006_intr_disable(struct cphy *phy)
143{
144 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
145}
146
147static int ael1006_intr_clear(struct cphy *phy)
148{
149 u32 val;
150
151 return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
152}
153
154static int ael1006_intr_handler(struct cphy *phy)
155{
156 unsigned int status;
157 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
158
159 if (err)
160 return err;
161 return (status & 1) ? cphy_cause_link_change : 0;
162}
163
164static int ael1006_power_down(struct cphy *phy, int enable) 134static int ael1006_power_down(struct cphy *phy, int enable)
165{ 135{
166 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 136 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
@@ -169,10 +139,10 @@ static int ael1006_power_down(struct cphy *phy, int enable)
169 139
170static struct cphy_ops ael1006_ops = { 140static struct cphy_ops ael1006_ops = {
171 .reset = ael1006_reset, 141 .reset = ael1006_reset,
172 .intr_enable = ael1006_intr_enable, 142 .intr_enable = t3_phy_lasi_intr_enable,
173 .intr_disable = ael1006_intr_disable, 143 .intr_disable = t3_phy_lasi_intr_disable,
174 .intr_clear = ael1006_intr_clear, 144 .intr_clear = t3_phy_lasi_intr_clear,
175 .intr_handler = ael1006_intr_handler, 145 .intr_handler = t3_phy_lasi_intr_handler,
176 .get_link_status = ael100x_get_link_status, 146 .get_link_status = ael100x_get_link_status,
177 .power_down = ael1006_power_down, 147 .power_down = ael1006_power_down,
178}; 148};
@@ -189,10 +159,10 @@ int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
189 159
190static struct cphy_ops qt2045_ops = { 160static struct cphy_ops qt2045_ops = {
191 .reset = ael1006_reset, 161 .reset = ael1006_reset,
192 .intr_enable = ael1006_intr_enable, 162 .intr_enable = t3_phy_lasi_intr_enable,
193 .intr_disable = ael1006_intr_disable, 163 .intr_disable = t3_phy_lasi_intr_disable,
194 .intr_clear = ael1006_intr_clear, 164 .intr_clear = t3_phy_lasi_intr_clear,
195 .intr_handler = ael1006_intr_handler, 165 .intr_handler = t3_phy_lasi_intr_handler,
196 .get_link_status = ael100x_get_link_status, 166 .get_link_status = ael100x_get_link_status,
197 .power_down = ael1006_power_down, 167 .power_down = ael1006_power_down,
198}; 168};
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 75b5ee61f45c..d1b6b1e62f41 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -522,7 +522,20 @@ enum {
522 MDIO_DEV_PMA_PMD = 1, 522 MDIO_DEV_PMA_PMD = 1,
523 MDIO_DEV_WIS = 2, 523 MDIO_DEV_WIS = 2,
524 MDIO_DEV_PCS = 3, 524 MDIO_DEV_PCS = 3,
525 MDIO_DEV_XGXS = 4 525 MDIO_DEV_XGXS = 4,
526 MDIO_DEV_ANEG = 7,
527 MDIO_DEV_VEND1 = 30,
528 MDIO_DEV_VEND2 = 31
529};
530
531/* LASI control and status registers */
532enum {
533 RX_ALARM_CTRL = 0x9000,
534 TX_ALARM_CTRL = 0x9001,
535 LASI_CTRL = 0x9002,
536 RX_ALARM_STAT = 0x9003,
537 TX_ALARM_STAT = 0x9004,
538 LASI_STAT = 0x9005
526}; 539};
527 540
528/* PHY loopback direction */ 541/* PHY loopback direction */
@@ -665,6 +678,10 @@ int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear,
665int t3_phy_reset(struct cphy *phy, int mmd, int wait); 678int t3_phy_reset(struct cphy *phy, int mmd, int wait);
666int t3_phy_advertise(struct cphy *phy, unsigned int advert); 679int t3_phy_advertise(struct cphy *phy, unsigned int advert);
667int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex); 680int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex);
681int t3_phy_lasi_intr_enable(struct cphy *phy);
682int t3_phy_lasi_intr_disable(struct cphy *phy);
683int t3_phy_lasi_intr_clear(struct cphy *phy);
684int t3_phy_lasi_intr_handler(struct cphy *phy);
668 685
669void t3_intr_enable(struct adapter *adapter); 686void t3_intr_enable(struct adapter *adapter);
670void t3_intr_disable(struct adapter *adapter); 687void t3_intr_disable(struct adapter *adapter);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 5b8251decbdc..bddcf945d6bb 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1516,11 +1516,22 @@ static int speed_duplex_to_caps(int speed, int duplex)
1516 1516
1517static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 1517static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1518{ 1518{
1519 int cap;
1519 struct port_info *p = netdev_priv(dev); 1520 struct port_info *p = netdev_priv(dev);
1520 struct link_config *lc = &p->link_config; 1521 struct link_config *lc = &p->link_config;
1521 1522
1522 if (!(lc->supported & SUPPORTED_Autoneg)) 1523 if (!(lc->supported & SUPPORTED_Autoneg)) {
1523 return -EOPNOTSUPP; /* can't change speed/duplex */ 1524 /*
1525 * PHY offers a single speed/duplex. See if that's what's
1526 * being requested.
1527 */
1528 if (cmd->autoneg == AUTONEG_DISABLE) {
1529 cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
1530 if (lc->supported & cap)
1531 return 0;
1532 }
1533 return -EINVAL;
1534 }
1524 1535
1525 if (cmd->autoneg == AUTONEG_DISABLE) { 1536 if (cmd->autoneg == AUTONEG_DISABLE) {
1526 int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); 1537 int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
@@ -2195,7 +2206,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
2195 mmd = data->phy_id >> 8; 2206 mmd = data->phy_id >> 8;
2196 if (!mmd) 2207 if (!mmd)
2197 mmd = MDIO_DEV_PCS; 2208 mmd = MDIO_DEV_PCS;
2198 else if (mmd > MDIO_DEV_XGXS) 2209 else if (mmd > MDIO_DEV_VEND2)
2199 return -EINVAL; 2210 return -EINVAL;
2200 2211
2201 ret = 2212 ret =
@@ -2221,7 +2232,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
2221 mmd = data->phy_id >> 8; 2232 mmd = data->phy_id >> 8;
2222 if (!mmd) 2233 if (!mmd)
2223 mmd = MDIO_DEV_PCS; 2234 mmd = MDIO_DEV_PCS;
2224 else if (mmd > MDIO_DEV_XGXS) 2235 else if (mmd > MDIO_DEV_VEND2)
2225 return -EINVAL; 2236 return -EINVAL;
2226 2237
2227 ret = 2238 ret =
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index bfce761156a1..58a3097579f9 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -442,6 +442,33 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
442 return mdio_write(phy, 0, MII_BMCR, ctl); 442 return mdio_write(phy, 0, MII_BMCR, ctl);
443} 443}
444 444
445int t3_phy_lasi_intr_enable(struct cphy *phy)
446{
447 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
448}
449
450int t3_phy_lasi_intr_disable(struct cphy *phy)
451{
452 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
453}
454
455int t3_phy_lasi_intr_clear(struct cphy *phy)
456{
457 u32 val;
458
459 return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
460}
461
462int t3_phy_lasi_intr_handler(struct cphy *phy)
463{
464 unsigned int status;
465 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
466
467 if (err)
468 return err;
469 return (status & 1) ? cphy_cause_link_change : 0;
470}
471
445static const struct adapter_info t3_adap_info[] = { 472static const struct adapter_info t3_adap_info[] = {
446 {2, 0, 473 {2, 0,
447 F_GPIO2_OEN | F_GPIO4_OEN | 474 F_GPIO2_OEN | F_GPIO4_OEN |
@@ -1132,6 +1159,15 @@ void t3_link_changed(struct adapter *adapter, int port_id)
1132 1159
1133 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); 1160 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
1134 1161
1162 if (lc->requested_fc & PAUSE_AUTONEG)
1163 fc &= lc->requested_fc;
1164 else
1165 fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
1166
1167 if (link_ok == lc->link_ok && speed == lc->speed &&
1168 duplex == lc->duplex && fc == lc->fc)
1169 return; /* nothing changed */
1170
1135 if (link_ok != lc->link_ok && adapter->params.rev > 0 && 1171 if (link_ok != lc->link_ok && adapter->params.rev > 0 &&
1136 uses_xaui(adapter)) { 1172 uses_xaui(adapter)) {
1137 if (link_ok) 1173 if (link_ok)
@@ -1142,10 +1178,6 @@ void t3_link_changed(struct adapter *adapter, int port_id)
1142 lc->link_ok = link_ok; 1178 lc->link_ok = link_ok;
1143 lc->speed = speed < 0 ? SPEED_INVALID : speed; 1179 lc->speed = speed < 0 ? SPEED_INVALID : speed;
1144 lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; 1180 lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
1145 if (lc->requested_fc & PAUSE_AUTONEG)
1146 fc &= lc->requested_fc;
1147 else
1148 fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
1149 1181
1150 if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { 1182 if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
1151 /* Set MAC speed, duplex, and flow control to match PHY. */ 1183 /* Set MAC speed, duplex, and flow control to match PHY. */
@@ -1191,7 +1223,6 @@ int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
1191 fc); 1223 fc);
1192 /* Also disables autoneg */ 1224 /* Also disables autoneg */
1193 phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); 1225 phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
1194 phy->ops->reset(phy, 0);
1195 } else 1226 } else
1196 phy->ops->autoneg_enable(phy); 1227 phy->ops->autoneg_enable(phy);
1197 } else { 1228 } else {