mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
r8152: fix flow control issue of RTL8156A
[ Upstream commit8ceda6d5a1] The feature of flow control becomes abnormal, if the device sends a pause frame and the tx/rx is disabled before sending a release frame. It causes the lost of packets. Set PLA_RX_FIFO_FULL and PLA_RX_FIFO_EMPTY to zeros before disabling the tx/rx. And, toggle FC_PATCH_TASK before enabling tx/rx to reset the flow control patch and timer. Then, the hardware could clear the state and the flow control becomes normal after enabling tx/rx. Besides, remove inline for fc_pause_on_auto() and fc_pause_off_auto(). Fixes:195aae321c("r8152: support new chips") Signed-off-by: Hayes Wang <hayeswang@realtek.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
5c37f7b20d
commit
435a5736c2
@@ -5986,6 +5986,25 @@ static void rtl8153_disable(struct r8152 *tp)
|
|||||||
r8153_aldps_en(tp, true);
|
r8153_aldps_en(tp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 fc_pause_on_auto(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 fc_pause_off_auto(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void r8156_fc_parameter(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp);
|
||||||
|
u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp);
|
||||||
|
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16);
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16);
|
||||||
|
}
|
||||||
|
|
||||||
static int rtl8156_enable(struct r8152 *tp)
|
static int rtl8156_enable(struct r8152 *tp)
|
||||||
{
|
{
|
||||||
u32 ocp_data;
|
u32 ocp_data;
|
||||||
@@ -5994,6 +6013,7 @@ static int rtl8156_enable(struct r8152 *tp)
|
|||||||
if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
r8156_fc_parameter(tp);
|
||||||
set_tx_qlen(tp);
|
set_tx_qlen(tp);
|
||||||
rtl_set_eee_plus(tp);
|
rtl_set_eee_plus(tp);
|
||||||
r8153_set_rx_early_timeout(tp);
|
r8153_set_rx_early_timeout(tp);
|
||||||
@@ -6025,9 +6045,24 @@ static int rtl8156_enable(struct r8152 *tp)
|
|||||||
ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
|
ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
|
||||||
|
ocp_data &= ~FC_PATCH_TASK;
|
||||||
|
ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
ocp_data |= FC_PATCH_TASK;
|
||||||
|
ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
|
||||||
|
|
||||||
return rtl_enable(tp);
|
return rtl_enable(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtl8156_disable(struct r8152 *tp)
|
||||||
|
{
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, 0);
|
||||||
|
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, 0);
|
||||||
|
|
||||||
|
rtl8153_disable(tp);
|
||||||
|
}
|
||||||
|
|
||||||
static int rtl8156b_enable(struct r8152 *tp)
|
static int rtl8156b_enable(struct r8152 *tp)
|
||||||
{
|
{
|
||||||
u32 ocp_data;
|
u32 ocp_data;
|
||||||
@@ -6429,25 +6464,6 @@ static void rtl8153c_up(struct r8152 *tp)
|
|||||||
r8153b_u1u2en(tp, true);
|
r8153b_u1u2en(tp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 fc_pause_on_auto(struct r8152 *tp)
|
|
||||||
{
|
|
||||||
return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 fc_pause_off_auto(struct r8152 *tp)
|
|
||||||
{
|
|
||||||
return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void r8156_fc_parameter(struct r8152 *tp)
|
|
||||||
{
|
|
||||||
u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp);
|
|
||||||
u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp);
|
|
||||||
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16);
|
|
||||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rtl8156_change_mtu(struct r8152 *tp)
|
static void rtl8156_change_mtu(struct r8152 *tp)
|
||||||
{
|
{
|
||||||
u32 rx_max_size = mtu_to_size(tp->netdev->mtu);
|
u32 rx_max_size = mtu_to_size(tp->netdev->mtu);
|
||||||
@@ -9377,7 +9393,7 @@ static int rtl_ops_init(struct r8152 *tp)
|
|||||||
case RTL_VER_10:
|
case RTL_VER_10:
|
||||||
ops->init = r8156_init;
|
ops->init = r8156_init;
|
||||||
ops->enable = rtl8156_enable;
|
ops->enable = rtl8156_enable;
|
||||||
ops->disable = rtl8153_disable;
|
ops->disable = rtl8156_disable;
|
||||||
ops->up = rtl8156_up;
|
ops->up = rtl8156_up;
|
||||||
ops->down = rtl8156_down;
|
ops->down = rtl8156_down;
|
||||||
ops->unload = rtl8153_unload;
|
ops->unload = rtl8153_unload;
|
||||||
|
|||||||
Reference in New Issue
Block a user