diff options
Diffstat (limited to 'drivers/net/cxgb3/t3_hw.c')
-rw-r--r-- | drivers/net/cxgb3/t3_hw.c | 243 |
1 files changed, 155 insertions, 88 deletions
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 04c0e90119af..968f64be3743 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. | 2 | * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
@@ -194,21 +194,18 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n, | |||
194 | static void mi1_init(struct adapter *adap, const struct adapter_info *ai) | 194 | static void mi1_init(struct adapter *adap, const struct adapter_info *ai) |
195 | { | 195 | { |
196 | u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1; | 196 | u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1; |
197 | u32 val = F_PREEN | V_MDIINV(ai->mdiinv) | V_MDIEN(ai->mdien) | | 197 | u32 val = F_PREEN | V_CLKDIV(clkdiv); |
198 | V_CLKDIV(clkdiv); | ||
199 | 198 | ||
200 | if (!(ai->caps & SUPPORTED_10000baseT_Full)) | ||
201 | val |= V_ST(1); | ||
202 | t3_write_reg(adap, A_MI1_CFG, val); | 199 | t3_write_reg(adap, A_MI1_CFG, val); |
203 | } | 200 | } |
204 | 201 | ||
205 | #define MDIO_ATTEMPTS 10 | 202 | #define MDIO_ATTEMPTS 20 |
206 | 203 | ||
207 | /* | 204 | /* |
208 | * MI1 read/write operations for direct-addressed PHYs. | 205 | * MI1 read/write operations for clause 22 PHYs. |
209 | */ | 206 | */ |
210 | static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, | 207 | static int t3_mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, |
211 | int reg_addr, unsigned int *valp) | 208 | int reg_addr, unsigned int *valp) |
212 | { | 209 | { |
213 | int ret; | 210 | int ret; |
214 | u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); | 211 | u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); |
@@ -217,16 +214,17 @@ static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, | |||
217 | return -EINVAL; | 214 | return -EINVAL; |
218 | 215 | ||
219 | mutex_lock(&adapter->mdio_lock); | 216 | mutex_lock(&adapter->mdio_lock); |
217 | t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); | ||
220 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 218 | t3_write_reg(adapter, A_MI1_ADDR, addr); |
221 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); | 219 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); |
222 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | 220 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); |
223 | if (!ret) | 221 | if (!ret) |
224 | *valp = t3_read_reg(adapter, A_MI1_DATA); | 222 | *valp = t3_read_reg(adapter, A_MI1_DATA); |
225 | mutex_unlock(&adapter->mdio_lock); | 223 | mutex_unlock(&adapter->mdio_lock); |
226 | return ret; | 224 | return ret; |
227 | } | 225 | } |
228 | 226 | ||
229 | static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, | 227 | static int t3_mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, |
230 | int reg_addr, unsigned int val) | 228 | int reg_addr, unsigned int val) |
231 | { | 229 | { |
232 | int ret; | 230 | int ret; |
@@ -236,37 +234,51 @@ static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, | |||
236 | return -EINVAL; | 234 | return -EINVAL; |
237 | 235 | ||
238 | mutex_lock(&adapter->mdio_lock); | 236 | mutex_lock(&adapter->mdio_lock); |
237 | t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), V_ST(1)); | ||
239 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 238 | t3_write_reg(adapter, A_MI1_ADDR, addr); |
240 | t3_write_reg(adapter, A_MI1_DATA, val); | 239 | t3_write_reg(adapter, A_MI1_DATA, val); |
241 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); | 240 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); |
242 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | 241 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10); |
243 | mutex_unlock(&adapter->mdio_lock); | 242 | mutex_unlock(&adapter->mdio_lock); |
244 | return ret; | 243 | return ret; |
245 | } | 244 | } |
246 | 245 | ||
247 | static const struct mdio_ops mi1_mdio_ops = { | 246 | static const struct mdio_ops mi1_mdio_ops = { |
248 | mi1_read, | 247 | t3_mi1_read, |
249 | mi1_write | 248 | t3_mi1_write |
250 | }; | 249 | }; |
251 | 250 | ||
252 | /* | 251 | /* |
252 | * Performs the address cycle for clause 45 PHYs. | ||
253 | * Must be called with the MDIO_LOCK held. | ||
254 | */ | ||
255 | static int mi1_wr_addr(struct adapter *adapter, int phy_addr, int mmd_addr, | ||
256 | int reg_addr) | ||
257 | { | ||
258 | u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); | ||
259 | |||
260 | t3_set_reg_field(adapter, A_MI1_CFG, V_ST(M_ST), 0); | ||
261 | t3_write_reg(adapter, A_MI1_ADDR, addr); | ||
262 | t3_write_reg(adapter, A_MI1_DATA, reg_addr); | ||
263 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); | ||
264 | return t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, | ||
265 | MDIO_ATTEMPTS, 10); | ||
266 | } | ||
267 | |||
268 | /* | ||
253 | * MI1 read/write operations for indirect-addressed PHYs. | 269 | * MI1 read/write operations for indirect-addressed PHYs. |
254 | */ | 270 | */ |
255 | static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, | 271 | static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, |
256 | int reg_addr, unsigned int *valp) | 272 | int reg_addr, unsigned int *valp) |
257 | { | 273 | { |
258 | int ret; | 274 | int ret; |
259 | u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); | ||
260 | 275 | ||
261 | mutex_lock(&adapter->mdio_lock); | 276 | mutex_lock(&adapter->mdio_lock); |
262 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 277 | ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr); |
263 | t3_write_reg(adapter, A_MI1_DATA, reg_addr); | ||
264 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); | ||
265 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | ||
266 | if (!ret) { | 278 | if (!ret) { |
267 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3)); | 279 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3)); |
268 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, | 280 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, |
269 | MDIO_ATTEMPTS, 20); | 281 | MDIO_ATTEMPTS, 10); |
270 | if (!ret) | 282 | if (!ret) |
271 | *valp = t3_read_reg(adapter, A_MI1_DATA); | 283 | *valp = t3_read_reg(adapter, A_MI1_DATA); |
272 | } | 284 | } |
@@ -278,18 +290,14 @@ static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, | |||
278 | int reg_addr, unsigned int val) | 290 | int reg_addr, unsigned int val) |
279 | { | 291 | { |
280 | int ret; | 292 | int ret; |
281 | u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); | ||
282 | 293 | ||
283 | mutex_lock(&adapter->mdio_lock); | 294 | mutex_lock(&adapter->mdio_lock); |
284 | t3_write_reg(adapter, A_MI1_ADDR, addr); | 295 | ret = mi1_wr_addr(adapter, phy_addr, mmd_addr, reg_addr); |
285 | t3_write_reg(adapter, A_MI1_DATA, reg_addr); | ||
286 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); | ||
287 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); | ||
288 | if (!ret) { | 296 | if (!ret) { |
289 | t3_write_reg(adapter, A_MI1_DATA, val); | 297 | t3_write_reg(adapter, A_MI1_DATA, val); |
290 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); | 298 | t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); |
291 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, | 299 | ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, |
292 | MDIO_ATTEMPTS, 20); | 300 | MDIO_ATTEMPTS, 10); |
293 | } | 301 | } |
294 | mutex_unlock(&adapter->mdio_lock); | 302 | mutex_unlock(&adapter->mdio_lock); |
295 | return ret; | 303 | return ret; |
@@ -400,6 +408,29 @@ int t3_phy_advertise(struct cphy *phy, unsigned int advert) | |||
400 | } | 408 | } |
401 | 409 | ||
402 | /** | 410 | /** |
411 | * t3_phy_advertise_fiber - set fiber PHY advertisement register | ||
412 | * @phy: the PHY to operate on | ||
413 | * @advert: bitmap of capabilities the PHY should advertise | ||
414 | * | ||
415 | * Sets a fiber PHY's advertisement register to advertise the | ||
416 | * requested capabilities. | ||
417 | */ | ||
418 | int t3_phy_advertise_fiber(struct cphy *phy, unsigned int advert) | ||
419 | { | ||
420 | unsigned int val = 0; | ||
421 | |||
422 | if (advert & ADVERTISED_1000baseT_Half) | ||
423 | val |= ADVERTISE_1000XHALF; | ||
424 | if (advert & ADVERTISED_1000baseT_Full) | ||
425 | val |= ADVERTISE_1000XFULL; | ||
426 | if (advert & ADVERTISED_Pause) | ||
427 | val |= ADVERTISE_1000XPAUSE; | ||
428 | if (advert & ADVERTISED_Asym_Pause) | ||
429 | val |= ADVERTISE_1000XPSE_ASYM; | ||
430 | return mdio_write(phy, 0, MII_ADVERTISE, val); | ||
431 | } | ||
432 | |||
433 | /** | ||
403 | * t3_set_phy_speed_duplex - force PHY speed and duplex | 434 | * t3_set_phy_speed_duplex - force PHY speed and duplex |
404 | * @phy: the PHY to operate on | 435 | * @phy: the PHY to operate on |
405 | * @speed: requested PHY speed | 436 | * @speed: requested PHY speed |
@@ -434,27 +465,52 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) | |||
434 | return mdio_write(phy, 0, MII_BMCR, ctl); | 465 | return mdio_write(phy, 0, MII_BMCR, ctl); |
435 | } | 466 | } |
436 | 467 | ||
468 | int t3_phy_lasi_intr_enable(struct cphy *phy) | ||
469 | { | ||
470 | return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); | ||
471 | } | ||
472 | |||
473 | int t3_phy_lasi_intr_disable(struct cphy *phy) | ||
474 | { | ||
475 | return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); | ||
476 | } | ||
477 | |||
478 | int t3_phy_lasi_intr_clear(struct cphy *phy) | ||
479 | { | ||
480 | u32 val; | ||
481 | |||
482 | return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); | ||
483 | } | ||
484 | |||
485 | int t3_phy_lasi_intr_handler(struct cphy *phy) | ||
486 | { | ||
487 | unsigned int status; | ||
488 | int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); | ||
489 | |||
490 | if (err) | ||
491 | return err; | ||
492 | return (status & 1) ? cphy_cause_link_change : 0; | ||
493 | } | ||
494 | |||
437 | static const struct adapter_info t3_adap_info[] = { | 495 | static const struct adapter_info t3_adap_info[] = { |
438 | {2, 0, 0, 0, | 496 | {2, 0, |
439 | F_GPIO2_OEN | F_GPIO4_OEN | | 497 | F_GPIO2_OEN | F_GPIO4_OEN | |
440 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, | 498 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, |
441 | 0, | ||
442 | &mi1_mdio_ops, "Chelsio PE9000"}, | 499 | &mi1_mdio_ops, "Chelsio PE9000"}, |
443 | {2, 0, 0, 0, | 500 | {2, 0, |
444 | F_GPIO2_OEN | F_GPIO4_OEN | | 501 | F_GPIO2_OEN | F_GPIO4_OEN | |
445 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, | 502 | F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, { S_GPIO3, S_GPIO5 }, 0, |
446 | 0, | ||
447 | &mi1_mdio_ops, "Chelsio T302"}, | 503 | &mi1_mdio_ops, "Chelsio T302"}, |
448 | {1, 0, 0, 0, | 504 | {1, 0, |
449 | F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | | 505 | F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | |
450 | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, | 506 | F_GPIO11_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, |
451 | 0, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, | 507 | { 0 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, |
452 | &mi1_mdio_ext_ops, "Chelsio T310"}, | 508 | &mi1_mdio_ext_ops, "Chelsio T310"}, |
453 | {2, 0, 0, 0, | 509 | {2, 0, |
454 | F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | | 510 | F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | |
455 | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | | 511 | F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | |
456 | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, | 512 | F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, |
457 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI, | 513 | { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI, |
458 | &mi1_mdio_ext_ops, "Chelsio T320"}, | 514 | &mi1_mdio_ext_ops, "Chelsio T320"}, |
459 | }; | 515 | }; |
460 | 516 | ||
@@ -467,29 +523,23 @@ const struct adapter_info *t3_get_adapter_info(unsigned int id) | |||
467 | return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL; | 523 | return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL; |
468 | } | 524 | } |
469 | 525 | ||
470 | #define CAPS_1G (SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | \ | 526 | struct port_type_info { |
471 | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII) | 527 | int (*phy_prep)(struct cphy *phy, struct adapter *adapter, |
472 | #define CAPS_10G (SUPPORTED_10000baseT_Full | SUPPORTED_AUI) | 528 | int phy_addr, const struct mdio_ops *ops); |
529 | }; | ||
473 | 530 | ||
474 | static const struct port_type_info port_types[] = { | 531 | static const struct port_type_info port_types[] = { |
475 | {NULL}, | 532 | { NULL }, |
476 | {t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE, | 533 | { t3_ael1002_phy_prep }, |
477 | "10GBASE-XR"}, | 534 | { t3_vsc8211_phy_prep }, |
478 | {t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, | 535 | { NULL}, |
479 | "10/100/1000BASE-T"}, | 536 | { t3_xaui_direct_phy_prep }, |
480 | {NULL, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, | 537 | { t3_ael2005_phy_prep }, |
481 | "10/100/1000BASE-T"}, | 538 | { t3_qt2045_phy_prep }, |
482 | {t3_xaui_direct_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, | 539 | { t3_ael1006_phy_prep }, |
483 | {NULL, CAPS_10G, "10GBASE-KX4"}, | 540 | { NULL }, |
484 | {t3_qt2045_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, | ||
485 | {t3_ael1006_phy_prep, CAPS_10G | SUPPORTED_FIBRE, | ||
486 | "10GBASE-SR"}, | ||
487 | {NULL, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, | ||
488 | }; | 541 | }; |
489 | 542 | ||
490 | #undef CAPS_1G | ||
491 | #undef CAPS_10G | ||
492 | |||
493 | #define VPD_ENTRY(name, len) \ | 543 | #define VPD_ENTRY(name, len) \ |
494 | u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] | 544 | u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] |
495 | 545 | ||
@@ -1132,6 +1182,15 @@ void t3_link_changed(struct adapter *adapter, int port_id) | |||
1132 | 1182 | ||
1133 | phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); | 1183 | phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); |
1134 | 1184 | ||
1185 | if (lc->requested_fc & PAUSE_AUTONEG) | ||
1186 | fc &= lc->requested_fc; | ||
1187 | else | ||
1188 | fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); | ||
1189 | |||
1190 | if (link_ok == lc->link_ok && speed == lc->speed && | ||
1191 | duplex == lc->duplex && fc == lc->fc) | ||
1192 | return; /* nothing changed */ | ||
1193 | |||
1135 | if (link_ok != lc->link_ok && adapter->params.rev > 0 && | 1194 | if (link_ok != lc->link_ok && adapter->params.rev > 0 && |
1136 | uses_xaui(adapter)) { | 1195 | uses_xaui(adapter)) { |
1137 | if (link_ok) | 1196 | if (link_ok) |
@@ -1142,10 +1201,6 @@ void t3_link_changed(struct adapter *adapter, int port_id) | |||
1142 | lc->link_ok = link_ok; | 1201 | lc->link_ok = link_ok; |
1143 | lc->speed = speed < 0 ? SPEED_INVALID : speed; | 1202 | lc->speed = speed < 0 ? SPEED_INVALID : speed; |
1144 | lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; | 1203 | 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 | 1204 | ||
1150 | if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { | 1205 | if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { |
1151 | /* Set MAC speed, duplex, and flow control to match PHY. */ | 1206 | /* Set MAC speed, duplex, and flow control to match PHY. */ |
@@ -1191,7 +1246,6 @@ int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) | |||
1191 | fc); | 1246 | fc); |
1192 | /* Also disables autoneg */ | 1247 | /* Also disables autoneg */ |
1193 | phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); | 1248 | phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); |
1194 | phy->ops->reset(phy, 0); | ||
1195 | } else | 1249 | } else |
1196 | phy->ops->autoneg_enable(phy); | 1250 | phy->ops->autoneg_enable(phy); |
1197 | } else { | 1251 | } else { |
@@ -1221,7 +1275,7 @@ struct intr_info { | |||
1221 | unsigned int mask; /* bits to check in interrupt status */ | 1275 | unsigned int mask; /* bits to check in interrupt status */ |
1222 | const char *msg; /* message to print or NULL */ | 1276 | const char *msg; /* message to print or NULL */ |
1223 | short stat_idx; /* stat counter to increment or -1 */ | 1277 | short stat_idx; /* stat counter to increment or -1 */ |
1224 | unsigned short fatal:1; /* whether the condition reported is fatal */ | 1278 | unsigned short fatal; /* whether the condition reported is fatal */ |
1225 | }; | 1279 | }; |
1226 | 1280 | ||
1227 | /** | 1281 | /** |
@@ -1682,25 +1736,23 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx) | |||
1682 | */ | 1736 | */ |
1683 | int t3_phy_intr_handler(struct adapter *adapter) | 1737 | int t3_phy_intr_handler(struct adapter *adapter) |
1684 | { | 1738 | { |
1685 | u32 mask, gpi = adapter_info(adapter)->gpio_intr; | ||
1686 | u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); | 1739 | u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); |
1687 | 1740 | ||
1688 | for_each_port(adapter, i) { | 1741 | for_each_port(adapter, i) { |
1689 | struct port_info *p = adap2pinfo(adapter, i); | 1742 | struct port_info *p = adap2pinfo(adapter, i); |
1690 | 1743 | ||
1691 | mask = gpi - (gpi & (gpi - 1)); | 1744 | if (!(p->phy.caps & SUPPORTED_IRQ)) |
1692 | gpi -= mask; | ||
1693 | |||
1694 | if (!(p->port_type->caps & SUPPORTED_IRQ)) | ||
1695 | continue; | 1745 | continue; |
1696 | 1746 | ||
1697 | if (cause & mask) { | 1747 | if (cause & (1 << adapter_info(adapter)->gpio_intr[i])) { |
1698 | int phy_cause = p->phy.ops->intr_handler(&p->phy); | 1748 | int phy_cause = p->phy.ops->intr_handler(&p->phy); |
1699 | 1749 | ||
1700 | if (phy_cause & cphy_cause_link_change) | 1750 | if (phy_cause & cphy_cause_link_change) |
1701 | t3_link_changed(adapter, i); | 1751 | t3_link_changed(adapter, i); |
1702 | if (phy_cause & cphy_cause_fifo_error) | 1752 | if (phy_cause & cphy_cause_fifo_error) |
1703 | p->phy.fifo_errors++; | 1753 | p->phy.fifo_errors++; |
1754 | if (phy_cause & cphy_cause_module_change) | ||
1755 | t3_os_phymod_changed(adapter, i); | ||
1704 | } | 1756 | } |
1705 | } | 1757 | } |
1706 | 1758 | ||
@@ -1763,6 +1815,17 @@ int t3_slow_intr_handler(struct adapter *adapter) | |||
1763 | return 1; | 1815 | return 1; |
1764 | } | 1816 | } |
1765 | 1817 | ||
1818 | static unsigned int calc_gpio_intr(struct adapter *adap) | ||
1819 | { | ||
1820 | unsigned int i, gpi_intr = 0; | ||
1821 | |||
1822 | for_each_port(adap, i) | ||
1823 | if ((adap2pinfo(adap, i)->phy.caps & SUPPORTED_IRQ) && | ||
1824 | adapter_info(adap)->gpio_intr[i]) | ||
1825 | gpi_intr |= 1 << adapter_info(adap)->gpio_intr[i]; | ||
1826 | return gpi_intr; | ||
1827 | } | ||
1828 | |||
1766 | /** | 1829 | /** |
1767 | * t3_intr_enable - enable interrupts | 1830 | * t3_intr_enable - enable interrupts |
1768 | * @adapter: the adapter whose interrupts should be enabled | 1831 | * @adapter: the adapter whose interrupts should be enabled |
@@ -1805,10 +1868,8 @@ void t3_intr_enable(struct adapter *adapter) | |||
1805 | t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK); | 1868 | t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK); |
1806 | } | 1869 | } |
1807 | 1870 | ||
1808 | t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, | 1871 | t3_write_reg(adapter, A_T3DBG_INT_ENABLE, calc_gpio_intr(adapter)); |
1809 | adapter_info(adapter)->gpio_intr); | 1872 | |
1810 | t3_write_reg(adapter, A_T3DBG_INT_ENABLE, | ||
1811 | adapter_info(adapter)->gpio_intr); | ||
1812 | if (is_pcie(adapter)) | 1873 | if (is_pcie(adapter)) |
1813 | t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK); | 1874 | t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK); |
1814 | else | 1875 | else |
@@ -3329,6 +3390,8 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params) | |||
3329 | init_hw_for_avail_ports(adapter, adapter->params.nports); | 3390 | init_hw_for_avail_ports(adapter, adapter->params.nports); |
3330 | t3_sge_init(adapter, &adapter->params.sge); | 3391 | t3_sge_init(adapter, &adapter->params.sge); |
3331 | 3392 | ||
3393 | t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, calc_gpio_intr(adapter)); | ||
3394 | |||
3332 | t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params); | 3395 | t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params); |
3333 | t3_write_reg(adapter, A_CIM_BOOT_CFG, | 3396 | t3_write_reg(adapter, A_CIM_BOOT_CFG, |
3334 | V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2)); | 3397 | V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2)); |
@@ -3488,7 +3551,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) | |||
3488 | * Older PCIe cards lose their config space during reset, PCI-X | 3551 | * Older PCIe cards lose their config space during reset, PCI-X |
3489 | * ones don't. | 3552 | * ones don't. |
3490 | */ | 3553 | */ |
3491 | static int t3_reset_adapter(struct adapter *adapter) | 3554 | int t3_reset_adapter(struct adapter *adapter) |
3492 | { | 3555 | { |
3493 | int i, save_and_restore_pcie = | 3556 | int i, save_and_restore_pcie = |
3494 | adapter->params.rev < T3_REV_B2 && is_pcie(adapter); | 3557 | adapter->params.rev < T3_REV_B2 && is_pcie(adapter); |
@@ -3556,7 +3619,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3556 | int reset) | 3619 | int reset) |
3557 | { | 3620 | { |
3558 | int ret; | 3621 | int ret; |
3559 | unsigned int i, j = 0; | 3622 | unsigned int i, j = -1; |
3560 | 3623 | ||
3561 | get_pci_mode(adapter, &adapter->params.pci); | 3624 | get_pci_mode(adapter, &adapter->params.pci); |
3562 | 3625 | ||
@@ -3620,16 +3683,18 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3620 | 3683 | ||
3621 | for_each_port(adapter, i) { | 3684 | for_each_port(adapter, i) { |
3622 | u8 hw_addr[6]; | 3685 | u8 hw_addr[6]; |
3686 | const struct port_type_info *pti; | ||
3623 | struct port_info *p = adap2pinfo(adapter, i); | 3687 | struct port_info *p = adap2pinfo(adapter, i); |
3624 | 3688 | ||
3625 | while (!adapter->params.vpd.port_type[j]) | 3689 | while (!adapter->params.vpd.port_type[++j]) |
3626 | ++j; | 3690 | ; |
3627 | 3691 | ||
3628 | p->port_type = &port_types[adapter->params.vpd.port_type[j]]; | 3692 | pti = &port_types[adapter->params.vpd.port_type[j]]; |
3629 | p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | 3693 | ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, |
3630 | ai->mdio_ops); | 3694 | ai->mdio_ops); |
3695 | if (ret) | ||
3696 | return ret; | ||
3631 | mac_prep(&p->mac, adapter, j); | 3697 | mac_prep(&p->mac, adapter, j); |
3632 | ++j; | ||
3633 | 3698 | ||
3634 | /* | 3699 | /* |
3635 | * The VPD EEPROM stores the base Ethernet address for the | 3700 | * The VPD EEPROM stores the base Ethernet address for the |
@@ -3643,9 +3708,9 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | |||
3643 | ETH_ALEN); | 3708 | ETH_ALEN); |
3644 | memcpy(adapter->port[i]->perm_addr, hw_addr, | 3709 | memcpy(adapter->port[i]->perm_addr, hw_addr, |
3645 | ETH_ALEN); | 3710 | ETH_ALEN); |
3646 | init_link_config(&p->link_config, p->port_type->caps); | 3711 | init_link_config(&p->link_config, p->phy.caps); |
3647 | p->phy.ops->power_down(&p->phy, 1); | 3712 | p->phy.ops->power_down(&p->phy, 1); |
3648 | if (!(p->port_type->caps & SUPPORTED_IRQ)) | 3713 | if (!(p->phy.caps & SUPPORTED_IRQ)) |
3649 | adapter->params.linkpoll_period = 10; | 3714 | adapter->params.linkpoll_period = 10; |
3650 | } | 3715 | } |
3651 | 3716 | ||
@@ -3661,7 +3726,7 @@ void t3_led_ready(struct adapter *adapter) | |||
3661 | int t3_replay_prep_adapter(struct adapter *adapter) | 3726 | int t3_replay_prep_adapter(struct adapter *adapter) |
3662 | { | 3727 | { |
3663 | const struct adapter_info *ai = adapter->params.info; | 3728 | const struct adapter_info *ai = adapter->params.info; |
3664 | unsigned int i, j = 0; | 3729 | unsigned int i, j = -1; |
3665 | int ret; | 3730 | int ret; |
3666 | 3731 | ||
3667 | early_hw_init(adapter, ai); | 3732 | early_hw_init(adapter, ai); |
@@ -3670,15 +3735,17 @@ int t3_replay_prep_adapter(struct adapter *adapter) | |||
3670 | return ret; | 3735 | return ret; |
3671 | 3736 | ||
3672 | for_each_port(adapter, i) { | 3737 | for_each_port(adapter, i) { |
3738 | const struct port_type_info *pti; | ||
3673 | struct port_info *p = adap2pinfo(adapter, i); | 3739 | struct port_info *p = adap2pinfo(adapter, i); |
3674 | while (!adapter->params.vpd.port_type[j]) | ||
3675 | ++j; | ||
3676 | 3740 | ||
3677 | p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | 3741 | while (!adapter->params.vpd.port_type[++j]) |
3678 | ai->mdio_ops); | 3742 | ; |
3679 | 3743 | ||
3744 | pti = &port_types[adapter->params.vpd.port_type[j]]; | ||
3745 | ret = pti->phy_prep(&p->phy, adapter, p->phy.addr, NULL); | ||
3746 | if (ret) | ||
3747 | return ret; | ||
3680 | p->phy.ops->power_down(&p->phy, 1); | 3748 | p->phy.ops->power_down(&p->phy, 1); |
3681 | ++j; | ||
3682 | } | 3749 | } |
3683 | 3750 | ||
3684 | return 0; | 3751 | return 0; |