From: Masakazu Mokuno [EMAIL PROTECTED]
Add Wake-on-LAN support to the PS3 Gelic network driver.
Other OS WOL support was introduced in PS3 system firmware
2.20.
Signed-off-by: Masakazu Mokuno [EMAIL PROTECTED]
Signed-off-by: Geoff Levand [EMAIL PROTECTED]
---
drivers/net/ps3_gelic_net.c | 81
drivers/net/ps3_gelic_net.h | 20 ++
2 files changed, 101 insertions(+)
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -1266,6 +1266,85 @@ int gelic_net_set_rx_csum(struct net_dev
return 0;
}
+static void gelic_net_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ if (0 = ps3_compare_firmware_version(2, 2, 0))
+ wol-supported = WAKE_MAGIC;
+ else
+ wol-supported = 0;
+
+ wol-wolopts = ps3_sys_manager_get_wol() ? wol-supported : 0;
+ memset(wol-sopass, 0, sizeof(wol-sopass));
+}
+static int gelic_net_set_wol(struct net_device *netdev,
+struct ethtool_wolinfo *wol)
+{
+ int status;
+ struct gelic_card *card;
+ u64 v1, v2;
+
+ if (ps3_compare_firmware_version(2, 2, 0) 0 ||
+ !capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (wol-wolopts ~WAKE_MAGIC)
+ return -EINVAL;
+
+ card = netdev_card(netdev);
+ if (wol-wolopts WAKE_MAGIC) {
+ status = lv1_net_control(bus_id(card), dev_id(card),
+GELIC_LV1_SET_WOL,
+GELIC_LV1_WOL_MAGIC_PACKET,
+0, GELIC_LV1_WOL_MP_ENABLE,
+v1, v2);
+ if (status) {
+ pr_info(%s: enabling WOL failed %d\n, __func__,
+ status);
+ status = -EIO;
+ goto done;
+ }
+ status = lv1_net_control(bus_id(card), dev_id(card),
+GELIC_LV1_SET_WOL,
+GELIC_LV1_WOL_ADD_MATCH_ADDR,
+0, GELIC_LV1_WOL_MATCH_ALL,
+v1, v2);
+ if (!status)
+ ps3_sys_manager_set_wol(1);
+ else {
+ pr_info(%s: enabling WOL filter failed %d\n,
+ __func__, status);
+ status = -EIO;
+ }
+ } else {
+ status = lv1_net_control(bus_id(card), dev_id(card),
+GELIC_LV1_SET_WOL,
+GELIC_LV1_WOL_MAGIC_PACKET,
+0, GELIC_LV1_WOL_MP_DISABLE,
+v1, v2);
+ if (status) {
+ pr_info(%s: disabling WOL failed %d\n, __func__,
+ status);
+ status = -EIO;
+ goto done;
+ }
+ status = lv1_net_control(bus_id(card), dev_id(card),
+GELIC_LV1_SET_WOL,
+GELIC_LV1_WOL_DELETE_MATCH_ADDR,
+0, GELIC_LV1_WOL_MATCH_ALL,
+v1, v2);
+ if (!status)
+ ps3_sys_manager_set_wol(0);
+ else {
+ pr_info(%s: removing WOL filter failed %d\n,
+ __func__, status);
+ status = -EIO;
+ }
+ }
+done:
+ return status;
+}
+
static struct ethtool_ops gelic_ether_ethtool_ops = {
.get_drvinfo= gelic_net_get_drvinfo,
.get_settings = gelic_ether_get_settings,
@@ -1274,6 +1353,8 @@ static struct ethtool_ops gelic_ether_et
.set_tx_csum= ethtool_op_set_tx_csum,
.get_rx_csum= gelic_net_get_rx_csum,
.set_rx_csum= gelic_net_set_rx_csum,
+ .get_wol= gelic_net_get_wol,
+ .set_wol= gelic_net_set_wol,
};
/**
--- a/drivers/net/ps3_gelic_net.h
+++ b/drivers/net/ps3_gelic_net.h
@@ -182,12 +182,32 @@ enum gelic_lv1_net_control_code {
GELIC_LV1_GET_ETH_PORT_STATUS = 2,
GELIC_LV1_SET_NEGOTIATION_MODE = 3,
GELIC_LV1_GET_VLAN_ID = 4,
+ GELIC_LV1_SET_WOL = 5,
GELIC_LV1_GET_CHANNEL = 6,
GELIC_LV1_POST_WLAN_CMD = 9,
GELIC_LV1_GET_WLAN_CMD_RESULT = 10,
GELIC_LV1_GET_WLAN_EVENT= 11
};
+/* for GELIC_LV1_SET_WOL */
+enum gelic_lv1_wol_command {
+ GELIC_LV1_WOL_MAGIC_PACKET = 1,
+ GELIC_LV1_WOL_ADD_MATCH_ADDR= 6,
+ GELIC_LV1_WOL_DELETE_MATCH_ADDR = 7,
+};
+
+/* for