aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHideyuki Sasaki <Hideyuki_Sasaki@hq.scei.sony.co.jp>2009-12-01 07:15:58 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-02 03:52:31 -0500
commit55873ed87fe6d34bd6f3a303c2d2ec6632c14525 (patch)
tree82367a91302a0456f9aff9798296c28528dcb906 /drivers
parentd4d7f1f9116089a4ae5102dcda35e8120308a515 (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')
-rw-r--r--drivers/net/ps3_gelic_net.c72
-rw-r--r--drivers/net/ps3_gelic_net.h2
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
110static 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
110void gelic_card_up(struct gelic_card *card) 128void 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
1278static 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
1255u32 gelic_net_get_rx_csum(struct net_device *netdev) 1317u32 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:
1349static const struct ethtool_ops gelic_ether_ethtool_ops = { 1411static 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