diff options
author | Hideyuki Sasaki <Hideyuki_Sasaki@hq.scei.sony.co.jp> | 2009-12-01 07:15:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-02 03:52:31 -0500 |
commit | 55873ed87fe6d34bd6f3a303c2d2ec6632c14525 (patch) | |
tree | 82367a91302a0456f9aff9798296c28528dcb906 /drivers/net/ps3_gelic_net.c | |
parent | d4d7f1f9116089a4ae5102dcda35e8120308a515 (diff) |
net/ps3: Add support for gelic link negotiation
Add ethtool_ops.set_settings support to the PS3 gelic network driver.
Allows manual setting of ethernet link speed.
Signed-off-by: Hideyuki Sasaki <xhide@rd.scei.sony.co.jp>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ps3_gelic_net.c')
-rw-r--r-- | drivers/net/ps3_gelic_net.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 06a29768a864..89c4948300a5 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c | |||
@@ -107,6 +107,24 @@ static void gelic_card_get_ether_port_status(struct gelic_card *card, | |||
107 | } | 107 | } |
108 | } | 108 | } |
109 | 109 | ||
110 | static int gelic_card_set_link_mode(struct gelic_card *card, int mode) | ||
111 | { | ||
112 | int status; | ||
113 | u64 v1, v2; | ||
114 | |||
115 | status = lv1_net_control(bus_id(card), dev_id(card), | ||
116 | GELIC_LV1_SET_NEGOTIATION_MODE, | ||
117 | GELIC_LV1_PHY_ETHERNET_0, mode, 0, &v1, &v2); | ||
118 | if (status) { | ||
119 | pr_info("%s: failed setting negotiation mode %d\n", __func__, | ||
120 | status); | ||
121 | return -EBUSY; | ||
122 | } | ||
123 | |||
124 | card->link_mode = mode; | ||
125 | return 0; | ||
126 | } | ||
127 | |||
110 | void gelic_card_up(struct gelic_card *card) | 128 | void gelic_card_up(struct gelic_card *card) |
111 | { | 129 | { |
112 | pr_debug("%s: called\n", __func__); | 130 | pr_debug("%s: called\n", __func__); |
@@ -1244,14 +1262,58 @@ static int gelic_ether_get_settings(struct net_device *netdev, | |||
1244 | cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | | 1262 | cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | |
1245 | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | | 1263 | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | |
1246 | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | | 1264 | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | |
1247 | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; | 1265 | SUPPORTED_1000baseT_Full; |
1248 | cmd->advertising = cmd->supported; | 1266 | cmd->advertising = cmd->supported; |
1249 | cmd->autoneg = AUTONEG_ENABLE; /* always enabled */ | 1267 | if (card->link_mode & GELIC_LV1_ETHER_AUTO_NEG) { |
1268 | cmd->autoneg = AUTONEG_ENABLE; | ||
1269 | } else { | ||
1270 | cmd->autoneg = AUTONEG_DISABLE; | ||
1271 | cmd->advertising &= ~ADVERTISED_Autoneg; | ||
1272 | } | ||
1250 | cmd->port = PORT_TP; | 1273 | cmd->port = PORT_TP; |
1251 | 1274 | ||
1252 | return 0; | 1275 | return 0; |
1253 | } | 1276 | } |
1254 | 1277 | ||
1278 | static int gelic_ether_set_settings(struct net_device *netdev, | ||
1279 | struct ethtool_cmd *cmd) | ||
1280 | { | ||
1281 | struct gelic_card *card = netdev_card(netdev); | ||
1282 | u64 mode; | ||
1283 | int ret; | ||
1284 | |||
1285 | if (cmd->autoneg == AUTONEG_ENABLE) { | ||
1286 | mode = GELIC_LV1_ETHER_AUTO_NEG; | ||
1287 | } else { | ||
1288 | switch (cmd->speed) { | ||
1289 | case SPEED_10: | ||
1290 | mode = GELIC_LV1_ETHER_SPEED_10; | ||
1291 | break; | ||
1292 | case SPEED_100: | ||
1293 | mode = GELIC_LV1_ETHER_SPEED_100; | ||
1294 | break; | ||
1295 | case SPEED_1000: | ||
1296 | mode = GELIC_LV1_ETHER_SPEED_1000; | ||
1297 | break; | ||
1298 | default: | ||
1299 | return -EINVAL; | ||
1300 | } | ||
1301 | if (cmd->duplex == DUPLEX_FULL) | ||
1302 | mode |= GELIC_LV1_ETHER_FULL_DUPLEX; | ||
1303 | else if (cmd->speed == SPEED_1000) { | ||
1304 | pr_info("1000 half duplex is not supported.\n"); | ||
1305 | return -EINVAL; | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | ret = gelic_card_set_link_mode(card, mode); | ||
1310 | |||
1311 | if (ret) | ||
1312 | return ret; | ||
1313 | |||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1255 | u32 gelic_net_get_rx_csum(struct net_device *netdev) | 1317 | u32 gelic_net_get_rx_csum(struct net_device *netdev) |
1256 | { | 1318 | { |
1257 | struct gelic_card *card = netdev_card(netdev); | 1319 | struct gelic_card *card = netdev_card(netdev); |
@@ -1349,6 +1411,7 @@ done: | |||
1349 | static const struct ethtool_ops gelic_ether_ethtool_ops = { | 1411 | static const struct ethtool_ops gelic_ether_ethtool_ops = { |
1350 | .get_drvinfo = gelic_net_get_drvinfo, | 1412 | .get_drvinfo = gelic_net_get_drvinfo, |
1351 | .get_settings = gelic_ether_get_settings, | 1413 | .get_settings = gelic_ether_get_settings, |
1414 | .set_settings = gelic_ether_set_settings, | ||
1352 | .get_link = ethtool_op_get_link, | 1415 | .get_link = ethtool_op_get_link, |
1353 | .get_tx_csum = ethtool_op_get_tx_csum, | 1416 | .get_tx_csum = ethtool_op_get_tx_csum, |
1354 | .set_tx_csum = ethtool_op_set_tx_csum, | 1417 | .set_tx_csum = ethtool_op_set_tx_csum, |
@@ -1657,6 +1720,8 @@ static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) | |||
1657 | /* get internal vlan info */ | 1720 | /* get internal vlan info */ |
1658 | gelic_card_get_vlan_info(card); | 1721 | gelic_card_get_vlan_info(card); |
1659 | 1722 | ||
1723 | card->link_mode = GELIC_LV1_ETHER_AUTO_NEG; | ||
1724 | |||
1660 | /* setup interrupt */ | 1725 | /* setup interrupt */ |
1661 | result = lv1_net_set_interrupt_status_indicator(bus_id(card), | 1726 | result = lv1_net_set_interrupt_status_indicator(bus_id(card), |
1662 | dev_id(card), | 1727 | dev_id(card), |
@@ -1773,6 +1838,9 @@ static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) | |||
1773 | struct net_device *netdev0; | 1838 | struct net_device *netdev0; |
1774 | pr_debug("%s: called\n", __func__); | 1839 | pr_debug("%s: called\n", __func__); |
1775 | 1840 | ||
1841 | /* set auto-negotiation */ | ||
1842 | gelic_card_set_link_mode(card, GELIC_LV1_ETHER_AUTO_NEG); | ||
1843 | |||
1776 | #ifdef CONFIG_GELIC_WIRELESS | 1844 | #ifdef CONFIG_GELIC_WIRELESS |
1777 | gelic_wl_driver_remove(card); | 1845 | gelic_wl_driver_remove(card); |
1778 | #endif | 1846 | #endif |