diff options
author | Hariprasad Shenai <hariprasad@chelsio.com> | 2014-12-22 04:44:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-22 16:35:28 -0500 |
commit | 5ad24def21b205a8e91925cd276b0a794b5ace82 (patch) | |
tree | a66c5e9af339f061142ece12c5eac5e9a19aa43e | |
parent | 3079c652141f9d6377417a7e8fd650c9948df65e (diff) |
cxgb4vf: Fix ethtool get_settings for VF driver
Decode and display Port Type and Module Type for ethtool get_settings() call
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 142 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | 54 |
4 files changed, 161 insertions, 41 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index d00a751f0588..6049f70e110c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | |||
@@ -96,6 +96,9 @@ struct port_info { | |||
96 | s16 xact_addr_filt; /* index of our MAC address filter */ | 96 | s16 xact_addr_filt; /* index of our MAC address filter */ |
97 | u16 rss_size; /* size of VI's RSS table slice */ | 97 | u16 rss_size; /* size of VI's RSS table slice */ |
98 | u8 pidx; /* index into adapter port[] */ | 98 | u8 pidx; /* index into adapter port[] */ |
99 | s8 mdio_addr; | ||
100 | u8 port_type; /* firmware port type */ | ||
101 | u8 mod_type; /* firmware module type */ | ||
99 | u8 port_id; /* physical port ID */ | 102 | u8 port_id; /* physical port ID */ |
100 | u8 nqsets; /* # of "Queue Sets" */ | 103 | u8 nqsets; /* # of "Queue Sets" */ |
101 | u8 first_qset; /* index of first "Queue Set" */ | 104 | u8 first_qset; /* index of first "Queue Set" */ |
@@ -522,6 +525,7 @@ static inline struct adapter *netdev2adap(const struct net_device *dev) | |||
522 | * is "contracted" to provide for the common code. | 525 | * is "contracted" to provide for the common code. |
523 | */ | 526 | */ |
524 | void t4vf_os_link_changed(struct adapter *, int, int); | 527 | void t4vf_os_link_changed(struct adapter *, int, int); |
528 | void t4vf_os_portmod_changed(struct adapter *, int); | ||
525 | 529 | ||
526 | /* | 530 | /* |
527 | * SGE function prototype declarations. | 531 | * SGE function prototype declarations. |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index aa74ec34a467..2215d432a059 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/etherdevice.h> | 44 | #include <linux/etherdevice.h> |
45 | #include <linux/debugfs.h> | 45 | #include <linux/debugfs.h> |
46 | #include <linux/ethtool.h> | 46 | #include <linux/ethtool.h> |
47 | #include <linux/mdio.h> | ||
47 | 48 | ||
48 | #include "t4vf_common.h" | 49 | #include "t4vf_common.h" |
49 | #include "t4vf_defs.h" | 50 | #include "t4vf_defs.h" |
@@ -210,6 +211,38 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok) | |||
210 | } | 211 | } |
211 | 212 | ||
212 | /* | 213 | /* |
214 | * THe port module type has changed on the indicated "port" (Virtual | ||
215 | * Interface). | ||
216 | */ | ||
217 | void t4vf_os_portmod_changed(struct adapter *adapter, int pidx) | ||
218 | { | ||
219 | static const char * const mod_str[] = { | ||
220 | NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" | ||
221 | }; | ||
222 | const struct net_device *dev = adapter->port[pidx]; | ||
223 | const struct port_info *pi = netdev_priv(dev); | ||
224 | |||
225 | if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) | ||
226 | dev_info(adapter->pdev_dev, "%s: port module unplugged\n", | ||
227 | dev->name); | ||
228 | else if (pi->mod_type < ARRAY_SIZE(mod_str)) | ||
229 | dev_info(adapter->pdev_dev, "%s: %s port module inserted\n", | ||
230 | dev->name, mod_str[pi->mod_type]); | ||
231 | else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) | ||
232 | dev_info(adapter->pdev_dev, "%s: unsupported optical port " | ||
233 | "module inserted\n", dev->name); | ||
234 | else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) | ||
235 | dev_info(adapter->pdev_dev, "%s: unknown port module inserted," | ||
236 | "forcing TWINAX\n", dev->name); | ||
237 | else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR) | ||
238 | dev_info(adapter->pdev_dev, "%s: transceiver module error\n", | ||
239 | dev->name); | ||
240 | else | ||
241 | dev_info(adapter->pdev_dev, "%s: unknown module type %d " | ||
242 | "inserted\n", dev->name, pi->mod_type); | ||
243 | } | ||
244 | |||
245 | /* | ||
213 | * Net device operations. | 246 | * Net device operations. |
214 | * ====================== | 247 | * ====================== |
215 | */ | 248 | */ |
@@ -1193,24 +1226,103 @@ static void cxgb4vf_poll_controller(struct net_device *dev) | |||
1193 | * state of the port to which we're linked. | 1226 | * state of the port to which we're linked. |
1194 | */ | 1227 | */ |
1195 | 1228 | ||
1196 | /* | 1229 | static unsigned int t4vf_from_fw_linkcaps(enum fw_port_type type, |
1197 | * Return current port link settings. | 1230 | unsigned int caps) |
1198 | */ | 1231 | { |
1199 | static int cxgb4vf_get_settings(struct net_device *dev, | 1232 | unsigned int v = 0; |
1200 | struct ethtool_cmd *cmd) | 1233 | |
1201 | { | 1234 | if (type == FW_PORT_TYPE_BT_SGMII || type == FW_PORT_TYPE_BT_XFI || |
1202 | const struct port_info *pi = netdev_priv(dev); | 1235 | type == FW_PORT_TYPE_BT_XAUI) { |
1236 | v |= SUPPORTED_TP; | ||
1237 | if (caps & FW_PORT_CAP_SPEED_100M) | ||
1238 | v |= SUPPORTED_100baseT_Full; | ||
1239 | if (caps & FW_PORT_CAP_SPEED_1G) | ||
1240 | v |= SUPPORTED_1000baseT_Full; | ||
1241 | if (caps & FW_PORT_CAP_SPEED_10G) | ||
1242 | v |= SUPPORTED_10000baseT_Full; | ||
1243 | } else if (type == FW_PORT_TYPE_KX4 || type == FW_PORT_TYPE_KX) { | ||
1244 | v |= SUPPORTED_Backplane; | ||
1245 | if (caps & FW_PORT_CAP_SPEED_1G) | ||
1246 | v |= SUPPORTED_1000baseKX_Full; | ||
1247 | if (caps & FW_PORT_CAP_SPEED_10G) | ||
1248 | v |= SUPPORTED_10000baseKX4_Full; | ||
1249 | } else if (type == FW_PORT_TYPE_KR) | ||
1250 | v |= SUPPORTED_Backplane | SUPPORTED_10000baseKR_Full; | ||
1251 | else if (type == FW_PORT_TYPE_BP_AP) | ||
1252 | v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC | | ||
1253 | SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full; | ||
1254 | else if (type == FW_PORT_TYPE_BP4_AP) | ||
1255 | v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC | | ||
1256 | SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full | | ||
1257 | SUPPORTED_10000baseKX4_Full; | ||
1258 | else if (type == FW_PORT_TYPE_FIBER_XFI || | ||
1259 | type == FW_PORT_TYPE_FIBER_XAUI || | ||
1260 | type == FW_PORT_TYPE_SFP || | ||
1261 | type == FW_PORT_TYPE_QSFP_10G || | ||
1262 | type == FW_PORT_TYPE_QSA) { | ||
1263 | v |= SUPPORTED_FIBRE; | ||
1264 | if (caps & FW_PORT_CAP_SPEED_1G) | ||
1265 | v |= SUPPORTED_1000baseT_Full; | ||
1266 | if (caps & FW_PORT_CAP_SPEED_10G) | ||
1267 | v |= SUPPORTED_10000baseT_Full; | ||
1268 | } else if (type == FW_PORT_TYPE_BP40_BA || | ||
1269 | type == FW_PORT_TYPE_QSFP) { | ||
1270 | v |= SUPPORTED_40000baseSR4_Full; | ||
1271 | v |= SUPPORTED_FIBRE; | ||
1272 | } | ||
1273 | |||
1274 | if (caps & FW_PORT_CAP_ANEG) | ||
1275 | v |= SUPPORTED_Autoneg; | ||
1276 | return v; | ||
1277 | } | ||
1278 | |||
1279 | static int cxgb4vf_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
1280 | { | ||
1281 | const struct port_info *p = netdev_priv(dev); | ||
1282 | |||
1283 | if (p->port_type == FW_PORT_TYPE_BT_SGMII || | ||
1284 | p->port_type == FW_PORT_TYPE_BT_XFI || | ||
1285 | p->port_type == FW_PORT_TYPE_BT_XAUI) | ||
1286 | cmd->port = PORT_TP; | ||
1287 | else if (p->port_type == FW_PORT_TYPE_FIBER_XFI || | ||
1288 | p->port_type == FW_PORT_TYPE_FIBER_XAUI) | ||
1289 | cmd->port = PORT_FIBRE; | ||
1290 | else if (p->port_type == FW_PORT_TYPE_SFP || | ||
1291 | p->port_type == FW_PORT_TYPE_QSFP_10G || | ||
1292 | p->port_type == FW_PORT_TYPE_QSA || | ||
1293 | p->port_type == FW_PORT_TYPE_QSFP) { | ||
1294 | if (p->mod_type == FW_PORT_MOD_TYPE_LR || | ||
1295 | p->mod_type == FW_PORT_MOD_TYPE_SR || | ||
1296 | p->mod_type == FW_PORT_MOD_TYPE_ER || | ||
1297 | p->mod_type == FW_PORT_MOD_TYPE_LRM) | ||
1298 | cmd->port = PORT_FIBRE; | ||
1299 | else if (p->mod_type == FW_PORT_MOD_TYPE_TWINAX_PASSIVE || | ||
1300 | p->mod_type == FW_PORT_MOD_TYPE_TWINAX_ACTIVE) | ||
1301 | cmd->port = PORT_DA; | ||
1302 | else | ||
1303 | cmd->port = PORT_OTHER; | ||
1304 | } else | ||
1305 | cmd->port = PORT_OTHER; | ||
1203 | 1306 | ||
1204 | cmd->supported = pi->link_cfg.supported; | 1307 | if (p->mdio_addr >= 0) { |
1205 | cmd->advertising = pi->link_cfg.advertising; | 1308 | cmd->phy_address = p->mdio_addr; |
1309 | cmd->transceiver = XCVR_EXTERNAL; | ||
1310 | cmd->mdio_support = p->port_type == FW_PORT_TYPE_BT_SGMII ? | ||
1311 | MDIO_SUPPORTS_C22 : MDIO_SUPPORTS_C45; | ||
1312 | } else { | ||
1313 | cmd->phy_address = 0; /* not really, but no better option */ | ||
1314 | cmd->transceiver = XCVR_INTERNAL; | ||
1315 | cmd->mdio_support = 0; | ||
1316 | } | ||
1317 | |||
1318 | cmd->supported = t4vf_from_fw_linkcaps(p->port_type, | ||
1319 | p->link_cfg.supported); | ||
1320 | cmd->advertising = t4vf_from_fw_linkcaps(p->port_type, | ||
1321 | p->link_cfg.advertising); | ||
1206 | ethtool_cmd_speed_set(cmd, | 1322 | ethtool_cmd_speed_set(cmd, |
1207 | netif_carrier_ok(dev) ? pi->link_cfg.speed : -1); | 1323 | netif_carrier_ok(dev) ? p->link_cfg.speed : 0); |
1208 | cmd->duplex = DUPLEX_FULL; | 1324 | cmd->duplex = DUPLEX_FULL; |
1209 | 1325 | cmd->autoneg = p->link_cfg.autoneg; | |
1210 | cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; | ||
1211 | cmd->phy_address = pi->port_id; | ||
1212 | cmd->transceiver = XCVR_EXTERNAL; | ||
1213 | cmd->autoneg = pi->link_cfg.autoneg; | ||
1214 | cmd->maxtxpkt = 0; | 1326 | cmd->maxtxpkt = 0; |
1215 | cmd->maxrxpkt = 0; | 1327 | cmd->maxrxpkt = 0; |
1216 | return 0; | 1328 | return 0; |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h index 8d3237f5e364..b9debb4f29a3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | |||
@@ -230,7 +230,7 @@ struct adapter_params { | |||
230 | 230 | ||
231 | static inline bool is_10g_port(const struct link_config *lc) | 231 | static inline bool is_10g_port(const struct link_config *lc) |
232 | { | 232 | { |
233 | return (lc->supported & SUPPORTED_10000baseT_Full) != 0; | 233 | return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0; |
234 | } | 234 | } |
235 | 235 | ||
236 | static inline bool is_x_10g_port(const struct link_config *lc) | 236 | static inline bool is_x_10g_port(const struct link_config *lc) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index 02e8833b7797..21dc9a20308c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | |||
@@ -245,6 +245,10 @@ static int hash_mac_addr(const u8 *addr) | |||
245 | return a & 0x3f; | 245 | return a & 0x3f; |
246 | } | 246 | } |
247 | 247 | ||
248 | #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ | ||
249 | FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \ | ||
250 | FW_PORT_CAP_SPEED_100G | FW_PORT_CAP_ANEG) | ||
251 | |||
248 | /** | 252 | /** |
249 | * init_link_config - initialize a link's SW state | 253 | * init_link_config - initialize a link's SW state |
250 | * @lc: structure holding the link state | 254 | * @lc: structure holding the link state |
@@ -259,8 +263,8 @@ static void init_link_config(struct link_config *lc, unsigned int caps) | |||
259 | lc->requested_speed = 0; | 263 | lc->requested_speed = 0; |
260 | lc->speed = 0; | 264 | lc->speed = 0; |
261 | lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; | 265 | lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; |
262 | if (lc->supported & SUPPORTED_Autoneg) { | 266 | if (lc->supported & FW_PORT_CAP_ANEG) { |
263 | lc->advertising = lc->supported; | 267 | lc->advertising = lc->supported & ADVERT_MASK; |
264 | lc->autoneg = AUTONEG_ENABLE; | 268 | lc->autoneg = AUTONEG_ENABLE; |
265 | lc->requested_fc |= PAUSE_AUTONEG; | 269 | lc->requested_fc |= PAUSE_AUTONEG; |
266 | } else { | 270 | } else { |
@@ -280,7 +284,6 @@ int t4vf_port_init(struct adapter *adapter, int pidx) | |||
280 | struct fw_vi_cmd vi_cmd, vi_rpl; | 284 | struct fw_vi_cmd vi_cmd, vi_rpl; |
281 | struct fw_port_cmd port_cmd, port_rpl; | 285 | struct fw_port_cmd port_cmd, port_rpl; |
282 | int v; | 286 | int v; |
283 | u32 word; | ||
284 | 287 | ||
285 | /* | 288 | /* |
286 | * Execute a VI Read command to get our Virtual Interface information | 289 | * Execute a VI Read command to get our Virtual Interface information |
@@ -319,19 +322,11 @@ int t4vf_port_init(struct adapter *adapter, int pidx) | |||
319 | if (v) | 322 | if (v) |
320 | return v; | 323 | return v; |
321 | 324 | ||
322 | v = 0; | 325 | v = be32_to_cpu(port_rpl.u.info.lstatus_to_modtype); |
323 | word = be16_to_cpu(port_rpl.u.info.pcap); | 326 | pi->port_type = FW_PORT_CMD_PTYPE_G(v); |
324 | if (word & FW_PORT_CAP_SPEED_100M) | 327 | pi->mod_type = FW_PORT_MOD_TYPE_NA; |
325 | v |= SUPPORTED_100baseT_Full; | 328 | |
326 | if (word & FW_PORT_CAP_SPEED_1G) | 329 | init_link_config(&pi->link_cfg, be16_to_cpu(port_rpl.u.info.pcap)); |
327 | v |= SUPPORTED_1000baseT_Full; | ||
328 | if (word & FW_PORT_CAP_SPEED_10G) | ||
329 | v |= SUPPORTED_10000baseT_Full; | ||
330 | if (word & FW_PORT_CAP_SPEED_40G) | ||
331 | v |= SUPPORTED_40000baseSR4_Full; | ||
332 | if (word & FW_PORT_CAP_ANEG) | ||
333 | v |= SUPPORTED_Autoneg; | ||
334 | init_link_config(&pi->link_cfg, v); | ||
335 | 330 | ||
336 | return 0; | 331 | return 0; |
337 | } | 332 | } |
@@ -1491,7 +1486,7 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
1491 | */ | 1486 | */ |
1492 | const struct fw_port_cmd *port_cmd = | 1487 | const struct fw_port_cmd *port_cmd = |
1493 | (const struct fw_port_cmd *)rpl; | 1488 | (const struct fw_port_cmd *)rpl; |
1494 | u32 word; | 1489 | u32 stat, mod; |
1495 | int action, port_id, link_ok, speed, fc, pidx; | 1490 | int action, port_id, link_ok, speed, fc, pidx; |
1496 | 1491 | ||
1497 | /* | 1492 | /* |
@@ -1509,21 +1504,21 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
1509 | port_id = FW_PORT_CMD_PORTID_G( | 1504 | port_id = FW_PORT_CMD_PORTID_G( |
1510 | be32_to_cpu(port_cmd->op_to_portid)); | 1505 | be32_to_cpu(port_cmd->op_to_portid)); |
1511 | 1506 | ||
1512 | word = be32_to_cpu(port_cmd->u.info.lstatus_to_modtype); | 1507 | stat = be32_to_cpu(port_cmd->u.info.lstatus_to_modtype); |
1513 | link_ok = (word & FW_PORT_CMD_LSTATUS_F) != 0; | 1508 | link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0; |
1514 | speed = 0; | 1509 | speed = 0; |
1515 | fc = 0; | 1510 | fc = 0; |
1516 | if (word & FW_PORT_CMD_RXPAUSE_F) | 1511 | if (stat & FW_PORT_CMD_RXPAUSE_F) |
1517 | fc |= PAUSE_RX; | 1512 | fc |= PAUSE_RX; |
1518 | if (word & FW_PORT_CMD_TXPAUSE_F) | 1513 | if (stat & FW_PORT_CMD_TXPAUSE_F) |
1519 | fc |= PAUSE_TX; | 1514 | fc |= PAUSE_TX; |
1520 | if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) | 1515 | if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) |
1521 | speed = 100; | 1516 | speed = 100; |
1522 | else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) | 1517 | else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) |
1523 | speed = 1000; | 1518 | speed = 1000; |
1524 | else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) | 1519 | else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) |
1525 | speed = 10000; | 1520 | speed = 10000; |
1526 | else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) | 1521 | else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) |
1527 | speed = 40000; | 1522 | speed = 40000; |
1528 | 1523 | ||
1529 | /* | 1524 | /* |
@@ -1540,12 +1535,21 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
1540 | continue; | 1535 | continue; |
1541 | 1536 | ||
1542 | lc = &pi->link_cfg; | 1537 | lc = &pi->link_cfg; |
1538 | |||
1539 | mod = FW_PORT_CMD_MODTYPE_G(stat); | ||
1540 | if (mod != pi->mod_type) { | ||
1541 | pi->mod_type = mod; | ||
1542 | t4vf_os_portmod_changed(adapter, pidx); | ||
1543 | } | ||
1544 | |||
1543 | if (link_ok != lc->link_ok || speed != lc->speed || | 1545 | if (link_ok != lc->link_ok || speed != lc->speed || |
1544 | fc != lc->fc) { | 1546 | fc != lc->fc) { |
1545 | /* something changed */ | 1547 | /* something changed */ |
1546 | lc->link_ok = link_ok; | 1548 | lc->link_ok = link_ok; |
1547 | lc->speed = speed; | 1549 | lc->speed = speed; |
1548 | lc->fc = fc; | 1550 | lc->fc = fc; |
1551 | lc->supported = | ||
1552 | be16_to_cpu(port_cmd->u.info.pcap); | ||
1549 | t4vf_os_link_changed(adapter, pidx, link_ok); | 1553 | t4vf_os_link_changed(adapter, pidx, link_ok); |
1550 | } | 1554 | } |
1551 | } | 1555 | } |