r8152: support WOL
Support WOL for RTL8152 and RTL8153. Signed-off-by: Hayes Wang <hayeswang@realtek.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7e9da48161
commit
21ff2e8976
@ -23,7 +23,7 @@
|
|||||||
#include <linux/ipv6.h>
|
#include <linux/ipv6.h>
|
||||||
|
|
||||||
/* Version Information */
|
/* Version Information */
|
||||||
#define DRIVER_VERSION "v1.04.0 (2014/01/15)"
|
#define DRIVER_VERSION "v1.05.0 (2014/02/18)"
|
||||||
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
|
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
|
||||||
#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
|
#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
|
||||||
#define MODULENAME "r8152"
|
#define MODULENAME "r8152"
|
||||||
@ -62,6 +62,8 @@
|
|||||||
#define PLA_RSTTELLY 0xe800
|
#define PLA_RSTTELLY 0xe800
|
||||||
#define PLA_CR 0xe813
|
#define PLA_CR 0xe813
|
||||||
#define PLA_CRWECR 0xe81c
|
#define PLA_CRWECR 0xe81c
|
||||||
|
#define PLA_CONFIG12 0xe81e /* CONFIG1, CONFIG2 */
|
||||||
|
#define PLA_CONFIG34 0xe820 /* CONFIG3, CONFIG4 */
|
||||||
#define PLA_CONFIG5 0xe822
|
#define PLA_CONFIG5 0xe822
|
||||||
#define PLA_PHY_PWR 0xe84c
|
#define PLA_PHY_PWR 0xe84c
|
||||||
#define PLA_OOB_CTRL 0xe84f
|
#define PLA_OOB_CTRL 0xe84f
|
||||||
@ -216,7 +218,14 @@
|
|||||||
/* PAL_BDC_CR */
|
/* PAL_BDC_CR */
|
||||||
#define ALDPS_PROXY_MODE 0x0001
|
#define ALDPS_PROXY_MODE 0x0001
|
||||||
|
|
||||||
|
/* PLA_CONFIG34 */
|
||||||
|
#define LINK_ON_WAKE_EN 0x0010
|
||||||
|
#define LINK_OFF_WAKE_EN 0x0008
|
||||||
|
|
||||||
/* PLA_CONFIG5 */
|
/* PLA_CONFIG5 */
|
||||||
|
#define BWF_EN 0x0040
|
||||||
|
#define MWF_EN 0x0020
|
||||||
|
#define UWF_EN 0x0010
|
||||||
#define LAN_WAKE_EN 0x0002
|
#define LAN_WAKE_EN 0x0002
|
||||||
|
|
||||||
/* PLA_LED_FEATURE */
|
/* PLA_LED_FEATURE */
|
||||||
@ -521,6 +530,7 @@ struct r8152 {
|
|||||||
} rtl_ops;
|
} rtl_ops;
|
||||||
|
|
||||||
int intr_interval;
|
int intr_interval;
|
||||||
|
u32 saved_wolopts;
|
||||||
u32 msg_enable;
|
u32 msg_enable;
|
||||||
u32 tx_qlen;
|
u32 tx_qlen;
|
||||||
u16 ocp_base;
|
u16 ocp_base;
|
||||||
@ -1798,6 +1808,74 @@ static void r8152_power_cut_en(struct r8152 *tp, bool enable)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
|
||||||
|
|
||||||
|
static u32 __rtl_get_wol(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
u32 ocp_data;
|
||||||
|
u32 wolopts = 0;
|
||||||
|
|
||||||
|
ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5);
|
||||||
|
if (!(ocp_data & LAN_WAKE_EN))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
|
||||||
|
if (ocp_data & LINK_ON_WAKE_EN)
|
||||||
|
wolopts |= WAKE_PHY;
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5);
|
||||||
|
if (ocp_data & UWF_EN)
|
||||||
|
wolopts |= WAKE_UCAST;
|
||||||
|
if (ocp_data & BWF_EN)
|
||||||
|
wolopts |= WAKE_BCAST;
|
||||||
|
if (ocp_data & MWF_EN)
|
||||||
|
wolopts |= WAKE_MCAST;
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
|
||||||
|
if (ocp_data & MAGIC_EN)
|
||||||
|
wolopts |= WAKE_MAGIC;
|
||||||
|
|
||||||
|
return wolopts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __rtl_set_wol(struct r8152 *tp, u32 wolopts)
|
||||||
|
{
|
||||||
|
u32 ocp_data;
|
||||||
|
|
||||||
|
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG34);
|
||||||
|
ocp_data &= ~LINK_ON_WAKE_EN;
|
||||||
|
if (wolopts & WAKE_PHY)
|
||||||
|
ocp_data |= LINK_ON_WAKE_EN;
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CONFIG5);
|
||||||
|
ocp_data &= ~(UWF_EN | BWF_EN | MWF_EN | LAN_WAKE_EN);
|
||||||
|
if (wolopts & WAKE_UCAST)
|
||||||
|
ocp_data |= UWF_EN;
|
||||||
|
if (wolopts & WAKE_BCAST)
|
||||||
|
ocp_data |= BWF_EN;
|
||||||
|
if (wolopts & WAKE_MCAST)
|
||||||
|
ocp_data |= MWF_EN;
|
||||||
|
if (wolopts & WAKE_ANY)
|
||||||
|
ocp_data |= LAN_WAKE_EN;
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data);
|
||||||
|
|
||||||
|
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
|
||||||
|
ocp_data &= ~MAGIC_EN;
|
||||||
|
if (wolopts & WAKE_MAGIC)
|
||||||
|
ocp_data |= MAGIC_EN;
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
|
||||||
|
|
||||||
|
if (wolopts & WAKE_ANY)
|
||||||
|
device_set_wakeup_enable(&tp->udev->dev, true);
|
||||||
|
else
|
||||||
|
device_set_wakeup_enable(&tp->udev->dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
static void rtl_phy_reset(struct r8152 *tp)
|
static void rtl_phy_reset(struct r8152 *tp)
|
||||||
{
|
{
|
||||||
u16 data;
|
u16 data;
|
||||||
@ -2002,10 +2080,6 @@ static void r8152b_enter_oob(struct r8152 *tp)
|
|||||||
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
||||||
|
|
||||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
|
|
||||||
ocp_data |= MAGIC_EN;
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
|
|
||||||
|
|
||||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
|
||||||
ocp_data |= CPCR_RX_VLAN;
|
ocp_data |= CPCR_RX_VLAN;
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
|
||||||
@ -2018,8 +2092,6 @@ static void r8152b_enter_oob(struct r8152 *tp)
|
|||||||
ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
|
ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
|
||||||
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
||||||
|
|
||||||
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
|
|
||||||
|
|
||||||
rxdy_gated_en(tp, false);
|
rxdy_gated_en(tp, false);
|
||||||
|
|
||||||
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
|
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
|
||||||
@ -2217,10 +2289,6 @@ static void r8153_enter_oob(struct r8152 *tp)
|
|||||||
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
||||||
|
|
||||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
|
|
||||||
ocp_data |= MAGIC_EN;
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
|
|
||||||
|
|
||||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
|
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
|
||||||
ocp_data &= ~TEREDO_WAKE_MASK;
|
ocp_data &= ~TEREDO_WAKE_MASK;
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
|
||||||
@ -2237,8 +2305,6 @@ static void r8153_enter_oob(struct r8152 *tp)
|
|||||||
ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
|
ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
|
||||||
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
||||||
|
|
||||||
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
|
|
||||||
|
|
||||||
rxdy_gated_en(tp, false);
|
rxdy_gated_en(tp, false);
|
||||||
|
|
||||||
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
|
ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
|
||||||
@ -2652,6 +2718,24 @@ static int rtl8152_resume(struct usb_interface *intf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct r8152 *tp = netdev_priv(dev);
|
||||||
|
|
||||||
|
wol->supported = WAKE_ANY;
|
||||||
|
wol->wolopts = __rtl_get_wol(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct r8152 *tp = netdev_priv(dev);
|
||||||
|
|
||||||
|
__rtl_set_wol(tp, wol->wolopts);
|
||||||
|
tp->saved_wolopts = wol->wolopts & WAKE_ANY;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void rtl8152_get_drvinfo(struct net_device *netdev,
|
static void rtl8152_get_drvinfo(struct net_device *netdev,
|
||||||
struct ethtool_drvinfo *info)
|
struct ethtool_drvinfo *info)
|
||||||
{
|
{
|
||||||
@ -2685,6 +2769,8 @@ static struct ethtool_ops ops = {
|
|||||||
.get_settings = rtl8152_get_settings,
|
.get_settings = rtl8152_get_settings,
|
||||||
.set_settings = rtl8152_set_settings,
|
.set_settings = rtl8152_set_settings,
|
||||||
.get_link = ethtool_op_get_link,
|
.get_link = ethtool_op_get_link,
|
||||||
|
.get_wol = rtl8152_get_wol,
|
||||||
|
.set_wol = rtl8152_set_wol,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
|
static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
|
||||||
@ -2888,6 +2974,12 @@ static int rtl8152_probe(struct usb_interface *intf,
|
|||||||
goto out1;
|
goto out1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tp->saved_wolopts = __rtl_get_wol(tp);
|
||||||
|
if (tp->saved_wolopts)
|
||||||
|
device_set_wakeup_enable(&udev->dev, true);
|
||||||
|
else
|
||||||
|
device_set_wakeup_enable(&udev->dev, false);
|
||||||
|
|
||||||
netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
|
netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user