diff options
| -rw-r--r-- | drivers/net/ps3_gelic_net.c | 72 | ||||
| -rw-r--r-- | drivers/net/ps3_gelic_net.h | 2 |
2 files changed, 72 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 |
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h index a09e4862706a..32521ae5e824 100644 --- a/drivers/net/ps3_gelic_net.h +++ b/drivers/net/ps3_gelic_net.h | |||
| @@ -307,6 +307,8 @@ struct gelic_card { | |||
| 307 | atomic_t users; | 307 | atomic_t users; |
| 308 | 308 | ||
| 309 | u64 ether_port_status; | 309 | u64 ether_port_status; |
| 310 | int link_mode; | ||
| 311 | |||
| 310 | /* original address returned by kzalloc */ | 312 | /* original address returned by kzalloc */ |
| 311 | void *unalign; | 313 | void *unalign; |
| 312 | 314 | ||
