diff options
Diffstat (limited to 'drivers/net/usb/r8152.c')
| -rw-r--r-- | drivers/net/usb/r8152.c | 188 | 
1 files changed, 120 insertions, 68 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 3eab74c7c554..604ef210a4de 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -24,7 +24,7 @@  #include <net/ip6_checksum.h>  /* Version Information */ -#define DRIVER_VERSION "v1.06.0 (2014/03/03)" +#define DRIVER_VERSION "v1.06.1 (2014/10/01)"  #define DRIVER_AUTHOR "Realtek linux nic maintainers <[email protected]>"  #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"  #define MODULENAME "r8152" @@ -59,6 +59,7 @@  #define PLA_WDT6_CTRL		0xe428  #define PLA_TCR0		0xe610  #define PLA_TCR1		0xe612 +#define PLA_MTPS		0xe615  #define PLA_TXFIFO_CTRL		0xe618  #define PLA_RSTTALLY		0xe800  #define PLA_CR			0xe813 @@ -180,6 +181,10 @@  /* PLA_TCR1 */  #define VERSION_MASK		0x7cf0 +/* PLA_MTPS */ +#define MTPS_JUMBO		(12 * 1024 / 64) +#define MTPS_DEFAULT		(6 * 1024 / 64) +  /* PLA_RSTTALLY */  #define TALLY_RESET		0x0001 @@ -440,8 +445,11 @@ enum rtl_register_content {  #define BYTE_EN_START_MASK	0x0f  #define BYTE_EN_END_MASK	0xf0 +#define RTL8153_MAX_PACKET	9216 /* 9K */ +#define RTL8153_MAX_MTU		(RTL8153_MAX_PACKET - VLAN_ETH_HLEN - VLAN_HLEN)  #define RTL8152_RMS		(VLAN_ETH_FRAME_LEN + VLAN_HLEN) -#define RTL8152_TX_TIMEOUT	(HZ) +#define RTL8153_RMS		RTL8153_MAX_PACKET +#define RTL8152_TX_TIMEOUT	(5 * HZ)  /* rtl8152 flags */  enum rtl8152_flags { @@ -1941,10 +1949,34 @@ static void rxdy_gated_en(struct r8152 *tp, bool enable)  	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);  } +static int rtl_start_rx(struct r8152 *tp) +{ +	int i, ret = 0; + +	INIT_LIST_HEAD(&tp->rx_done); +	for (i = 0; i < RTL8152_MAX_RX; i++) { +		INIT_LIST_HEAD(&tp->rx_info[i].list); +		ret = r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL); +		if (ret) +			break; +	} + +	return ret; +} + +static int rtl_stop_rx(struct r8152 *tp) +{ +	int i; + +	for (i = 0; i < RTL8152_MAX_RX; i++) +		usb_kill_urb(tp->rx_info[i].urb); + +	return 0; +} +  static int rtl_enable(struct r8152 *tp)  {  	u32 ocp_data; -	int i, ret;  	r8152b_reset_packet_filter(tp); @@ -1954,14 +1986,7 @@ static int rtl_enable(struct r8152 *tp)  	rxdy_gated_en(tp, false); -	INIT_LIST_HEAD(&tp->rx_done); -	ret = 0; -	for (i = 0; i < RTL8152_MAX_RX; i++) { -		INIT_LIST_HEAD(&tp->rx_info[i].list); -		ret |= r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL); -	} - -	return ret; +	return rtl_start_rx(tp);  }  static int rtl8152_enable(struct r8152 *tp) @@ -2011,7 +2036,7 @@ static int rtl8153_enable(struct r8152 *tp)  	return rtl_enable(tp);  } -static void rtl8152_disable(struct r8152 *tp) +static void rtl_disable(struct r8152 *tp)  {  	u32 ocp_data;  	int i; @@ -2045,8 +2070,7 @@ static void rtl8152_disable(struct r8152 *tp)  		mdelay(1);  	} -	for (i = 0; i < RTL8152_MAX_RX; i++) -		usb_kill_urb(tp->rx_info[i].urb); +	rtl_stop_rx(tp);  	rtl8152_nic_reset(tp);  } @@ -2177,28 +2201,6 @@ static void rtl_phy_reset(struct r8152 *tp)  	}  } -static void rtl_clear_bp(struct r8152 *tp) -{ -	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0); -	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0); -	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0); -	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0); -	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0); -	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0); -	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0); -	ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0); -	mdelay(3); -	ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0); -	ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0); -} - -static void r8153_clear_bp(struct r8152 *tp) -{ -	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0); -	ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0); -	rtl_clear_bp(tp); -} -  static void r8153_teredo_off(struct r8152 *tp)  {  	u32 ocp_data; @@ -2224,6 +2226,13 @@ static inline void r8152b_enable_aldps(struct r8152 *tp)  					    LINKENA | DIS_SDSAVE);  } +static void rtl8152_disable(struct r8152 *tp) +{ +	r8152b_disable_aldps(tp); +	rtl_disable(tp); +	r8152b_enable_aldps(tp); +} +  static void r8152b_hw_phy_cfg(struct r8152 *tp)  {  	u16 data; @@ -2234,11 +2243,6 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp)  		r8152_mdio_write(tp, MII_BMCR, data);  	} -	r8152b_disable_aldps(tp); - -	rtl_clear_bp(tp); - -	r8152b_enable_aldps(tp);  	set_bit(PHY_RESET, &tp->flags);  } @@ -2247,9 +2251,6 @@ static void r8152b_exit_oob(struct r8152 *tp)  	u32 ocp_data;  	int i; -	if (test_bit(RTL8152_UNPLUG, &tp->flags)) -		return; -  	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);  	ocp_data &= ~RCR_ACPT_ALL;  	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); @@ -2339,7 +2340,7 @@ static void r8152b_enter_oob(struct r8152 *tp)  	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);  	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB); -	rtl8152_disable(tp); +	rtl_disable(tp);  	for (i = 0; i < 1000; i++) {  		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); @@ -2392,8 +2393,6 @@ static void r8153_hw_phy_cfg(struct r8152 *tp)  		r8152_mdio_write(tp, MII_BMCR, data);  	} -	r8153_clear_bp(tp); -  	if (tp->version == RTL_VER_03) {  		data = ocp_reg_read(tp, OCP_EEE_CFG);  		data &= ~CTAP_SHORT_EN; @@ -2477,9 +2476,6 @@ static void r8153_first_init(struct r8152 *tp)  	u32 ocp_data;  	int i; -	if (test_bit(RTL8152_UNPLUG, &tp->flags)) -		return; -  	rxdy_gated_en(tp, true);  	r8153_teredo_off(tp); @@ -2521,7 +2517,8 @@ static void r8153_first_init(struct r8152 *tp)  	ocp_data &= ~CPCR_RX_VLAN;  	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); -	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); +	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS); +	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);  	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);  	ocp_data |= TCR0_AUTO_FIFO; @@ -2551,7 +2548,7 @@ static void r8153_enter_oob(struct r8152 *tp)  	ocp_data &= ~NOW_IS_OOB;  	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); -	rtl8152_disable(tp); +	rtl_disable(tp);  	for (i = 0; i < 1000; i++) {  		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); @@ -2571,7 +2568,7 @@ static void r8153_enter_oob(struct r8152 *tp)  		mdelay(1);  	} -	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); +	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);  	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);  	ocp_data &= ~TEREDO_WAKE_MASK; @@ -2615,6 +2612,13 @@ static void r8153_enable_aldps(struct r8152 *tp)  	ocp_reg_write(tp, OCP_POWER_CFG, data);  } +static void rtl8153_disable(struct r8152 *tp) +{ +	r8153_disable_aldps(tp); +	rtl_disable(tp); +	r8153_enable_aldps(tp); +} +  static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)  {  	u16 bmcr, anar, gbcr; @@ -2705,6 +2709,16 @@ out:  	return ret;  } +static void rtl8152_up(struct r8152 *tp) +{ +	if (test_bit(RTL8152_UNPLUG, &tp->flags)) +		return; + +	r8152b_disable_aldps(tp); +	r8152b_exit_oob(tp); +	r8152b_enable_aldps(tp); +} +  static void rtl8152_down(struct r8152 *tp)  {  	if (test_bit(RTL8152_UNPLUG, &tp->flags)) { @@ -2718,6 +2732,16 @@ static void rtl8152_down(struct r8152 *tp)  	r8152b_enable_aldps(tp);  } +static void rtl8153_up(struct r8152 *tp) +{ +	if (test_bit(RTL8152_UNPLUG, &tp->flags)) +		return; + +	r8153_disable_aldps(tp); +	r8153_first_init(tp); +	r8153_enable_aldps(tp); +} +  static void rtl8153_down(struct r8152 *tp)  {  	if (test_bit(RTL8152_UNPLUG, &tp->flags)) { @@ -2937,6 +2961,8 @@ static void r8152b_init(struct r8152 *tp)  	if (test_bit(RTL8152_UNPLUG, &tp->flags))  		return; +	r8152b_disable_aldps(tp); +  	if (tp->version == RTL_VER_01) {  		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);  		ocp_data &= ~LED_MODE_MASK; @@ -2975,6 +3001,7 @@ static void r8153_init(struct r8152 *tp)  	if (test_bit(RTL8152_UNPLUG, &tp->flags))  		return; +	r8153_disable_aldps(tp);  	r8153_u1u2en(tp, false);  	for (i = 0; i < 500; i++) { @@ -3046,13 +3073,14 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)  		clear_bit(WORK_ENABLE, &tp->flags);  		usb_kill_urb(tp->intr_urb);  		cancel_delayed_work_sync(&tp->schedule); +		tasklet_disable(&tp->tl);  		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { +			rtl_stop_rx(tp);  			rtl_runtime_suspend_enable(tp, true);  		} else { -			tasklet_disable(&tp->tl);  			tp->rtl_ops.down(tp); -			tasklet_enable(&tp->tl);  		} +		tasklet_enable(&tp->tl);  	}  	return 0; @@ -3071,17 +3099,18 @@ static int rtl8152_resume(struct usb_interface *intf)  		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {  			rtl_runtime_suspend_enable(tp, false);  			clear_bit(SELECTIVE_SUSPEND, &tp->flags); +			set_bit(WORK_ENABLE, &tp->flags);  			if (tp->speed & LINK_STATUS) -				tp->rtl_ops.disable(tp); +				rtl_start_rx(tp);  		} else {  			tp->rtl_ops.up(tp);  			rtl8152_set_speed(tp, AUTONEG_ENABLE,  				tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,  				DUPLEX_FULL); +			tp->speed = 0; +			netif_carrier_off(tp->netdev); +			set_bit(WORK_ENABLE, &tp->flags);  		} -		tp->speed = 0; -		netif_carrier_off(tp->netdev); -		set_bit(WORK_ENABLE, &tp->flags);  		usb_submit_urb(tp->intr_urb, GFP_KERNEL);  	} @@ -3288,6 +3317,26 @@ out:  	return res;  } +static int rtl8152_change_mtu(struct net_device *dev, int new_mtu) +{ +	struct r8152 *tp = netdev_priv(dev); + +	switch (tp->version) { +	case RTL_VER_01: +	case RTL_VER_02: +		return eth_change_mtu(dev, new_mtu); +	default: +		break; +	} + +	if (new_mtu < 68 || new_mtu > RTL8153_MAX_MTU) +		return -EINVAL; + +	dev->mtu = new_mtu; + +	return 0; +} +  static const struct net_device_ops rtl8152_netdev_ops = {  	.ndo_open		= rtl8152_open,  	.ndo_stop		= rtl8152_close, @@ -3296,8 +3345,7 @@ static const struct net_device_ops rtl8152_netdev_ops = {  	.ndo_tx_timeout		= rtl8152_tx_timeout,  	.ndo_set_rx_mode	= rtl8152_set_rx_mode,  	.ndo_set_mac_address	= rtl8152_set_mac_address, - -	.ndo_change_mtu		= eth_change_mtu, +	.ndo_change_mtu		= rtl8152_change_mtu,  	.ndo_validate_addr	= eth_validate_addr,  }; @@ -3349,7 +3397,7 @@ static void rtl8153_unload(struct r8152 *tp)  	if (test_bit(RTL8152_UNPLUG, &tp->flags))  		return; -	r8153_power_cut_en(tp, true); +	r8153_power_cut_en(tp, false);  }  static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) @@ -3364,7 +3412,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)  			ops->init		= r8152b_init;  			ops->enable		= rtl8152_enable;  			ops->disable		= rtl8152_disable; -			ops->up			= r8152b_exit_oob; +			ops->up			= rtl8152_up;  			ops->down		= rtl8152_down;  			ops->unload		= rtl8152_unload;  			ret = 0; @@ -3372,8 +3420,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)  		case PRODUCT_ID_RTL8153:  			ops->init		= r8153_init;  			ops->enable		= rtl8153_enable; -			ops->disable		= rtl8152_disable; -			ops->up			= r8153_first_init; +			ops->disable		= rtl8153_disable; +			ops->up			= rtl8153_up;  			ops->down		= rtl8153_down;  			ops->unload		= rtl8153_unload;  			ret = 0; @@ -3388,8 +3436,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)  		case PRODUCT_ID_SAMSUNG:  			ops->init		= r8153_init;  			ops->enable		= rtl8153_enable; -			ops->disable		= rtl8152_disable; -			ops->up			= r8153_first_init; +			ops->disable		= rtl8153_disable; +			ops->up			= rtl8153_up;  			ops->down		= rtl8153_down;  			ops->unload		= rtl8153_unload;  			ret = 0; @@ -3502,7 +3550,11 @@ static void rtl8152_disconnect(struct usb_interface *intf)  	usb_set_intfdata(intf, NULL);  	if (tp) { -		set_bit(RTL8152_UNPLUG, &tp->flags); +		struct usb_device *udev = tp->udev; + +		if (udev->state == USB_STATE_NOTATTACHED) +			set_bit(RTL8152_UNPLUG, &tp->flags); +  		tasklet_kill(&tp->tl);  		unregister_netdev(tp->netdev);  		tp->rtl_ops.unload(tp);  |