Commit 2786b2ba authored by hayeswang's avatar hayeswang Committed by Kleber Sacilotto de Souza

r8152: prevent the driver from transmitting packets with carrier off

BugLink: http://bugs.launchpad.net/bugs/1745054

[ Upstream commit 2f25abe6 ]

The linking status may be changed when autosuspend. And, after
autoresume, the driver may try to transmit packets when the device
is carrier off, because the interrupt transfer doesn't update the
linking status, yet. And, if the device is in ALDPS mode, the device
would stop working.

The another similar case is
 1. unplug the cable.
 2. interrupt transfer queue a work_queue for linking change.
 3. device enters the ALDPS mode.
 4. a tx occurs before the work_queue is called.
Signed-off-by: default avatarHayes Wang <hayeswang@realtek.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
parent 4cf81b48
...@@ -1280,6 +1280,7 @@ static void intr_callback(struct urb *urb) ...@@ -1280,6 +1280,7 @@ static void intr_callback(struct urb *urb)
} }
} else { } else {
if (netif_carrier_ok(tp->netdev)) { if (netif_carrier_ok(tp->netdev)) {
netif_stop_queue(tp->netdev);
set_bit(RTL8152_LINK_CHG, &tp->flags); set_bit(RTL8152_LINK_CHG, &tp->flags);
schedule_delayed_work(&tp->schedule, 0); schedule_delayed_work(&tp->schedule, 0);
} }
...@@ -3074,6 +3075,9 @@ static void set_carrier(struct r8152 *tp) ...@@ -3074,6 +3075,9 @@ static void set_carrier(struct r8152 *tp)
napi_enable(&tp->napi); napi_enable(&tp->napi);
netif_wake_queue(netdev); netif_wake_queue(netdev);
netif_info(tp, link, netdev, "carrier on\n"); netif_info(tp, link, netdev, "carrier on\n");
} else if (netif_queue_stopped(netdev) &&
skb_queue_len(&tp->tx_queue) < tp->tx_qlen) {
netif_wake_queue(netdev);
} }
} else { } else {
if (netif_carrier_ok(netdev)) { if (netif_carrier_ok(netdev)) {
...@@ -3634,8 +3638,18 @@ static int rtl8152_resume(struct usb_interface *intf) ...@@ -3634,8 +3638,18 @@ static int rtl8152_resume(struct usb_interface *intf)
clear_bit(SELECTIVE_SUSPEND, &tp->flags); clear_bit(SELECTIVE_SUSPEND, &tp->flags);
napi_disable(&tp->napi); napi_disable(&tp->napi);
set_bit(WORK_ENABLE, &tp->flags); set_bit(WORK_ENABLE, &tp->flags);
if (netif_carrier_ok(tp->netdev))
rtl_start_rx(tp); if (netif_carrier_ok(tp->netdev)) {
if (rtl8152_get_speed(tp) & LINK_STATUS) {
rtl_start_rx(tp);
} else {
netif_carrier_off(tp->netdev);
tp->rtl_ops.disable(tp);
netif_info(tp, link, tp->netdev,
"linking down\n");
}
}
napi_enable(&tp->napi); napi_enable(&tp->napi);
} else { } else {
tp->rtl_ops.up(tp); tp->rtl_ops.up(tp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment