Commit d2187f8e authored by Hayes Wang's avatar Hayes Wang Committed by David S. Miller

r8152: divide the tx and rx bottom functions

Move the tx bottom function from NAPI to a new tasklet. Then, for
multi-cores, the bottom functions of tx and rx may be run at same
time with different cores. This is used to improve performance.

On x86, Tx/Rx 943/943 Mbits/sec -> 945/944.
For arm platform, Tx/Rx: 917/917 Mbits/sec -> 933/933.
Signed-off-by: default avatarHayes Wang <hayeswang@realtek.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 932630fa
...@@ -619,7 +619,7 @@ enum rtl8152_flags { ...@@ -619,7 +619,7 @@ enum rtl8152_flags {
RTL8152_LINK_CHG, RTL8152_LINK_CHG,
SELECTIVE_SUSPEND, SELECTIVE_SUSPEND,
PHY_RESET, PHY_RESET,
SCHEDULE_NAPI, SCHEDULE_TASKLET,
GREEN_ETHERNET, GREEN_ETHERNET,
DELL_TB_RX_AGG_BUG, DELL_TB_RX_AGG_BUG,
}; };
...@@ -733,6 +733,7 @@ struct r8152 { ...@@ -733,6 +733,7 @@ struct r8152 {
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
struct notifier_block pm_notifier; struct notifier_block pm_notifier;
#endif #endif
struct tasklet_struct tx_tl;
struct rtl_ops { struct rtl_ops {
void (*init)(struct r8152 *); void (*init)(struct r8152 *);
...@@ -1401,7 +1402,7 @@ static void write_bulk_callback(struct urb *urb) ...@@ -1401,7 +1402,7 @@ static void write_bulk_callback(struct urb *urb)
return; return;
if (!skb_queue_empty(&tp->tx_queue)) if (!skb_queue_empty(&tp->tx_queue))
napi_schedule(&tp->napi); tasklet_schedule(&tp->tx_tl);
} }
static void intr_callback(struct urb *urb) static void intr_callback(struct urb *urb)
...@@ -2179,8 +2180,12 @@ static void tx_bottom(struct r8152 *tp) ...@@ -2179,8 +2180,12 @@ static void tx_bottom(struct r8152 *tp)
} while (res == 0); } while (res == 0);
} }
static void bottom_half(struct r8152 *tp) static void bottom_half(unsigned long data)
{ {
struct r8152 *tp;
tp = (struct r8152 *)data;
if (test_bit(RTL8152_UNPLUG, &tp->flags)) if (test_bit(RTL8152_UNPLUG, &tp->flags))
return; return;
...@@ -2192,7 +2197,7 @@ static void bottom_half(struct r8152 *tp) ...@@ -2192,7 +2197,7 @@ static void bottom_half(struct r8152 *tp)
if (!netif_carrier_ok(tp->netdev)) if (!netif_carrier_ok(tp->netdev))
return; return;
clear_bit(SCHEDULE_NAPI, &tp->flags); clear_bit(SCHEDULE_TASKLET, &tp->flags);
tx_bottom(tp); tx_bottom(tp);
} }
...@@ -2203,16 +2208,12 @@ static int r8152_poll(struct napi_struct *napi, int budget) ...@@ -2203,16 +2208,12 @@ static int r8152_poll(struct napi_struct *napi, int budget)
int work_done; int work_done;
work_done = rx_bottom(tp, budget); work_done = rx_bottom(tp, budget);
bottom_half(tp);
if (work_done < budget) { if (work_done < budget) {
if (!napi_complete_done(napi, work_done)) if (!napi_complete_done(napi, work_done))
goto out; goto out;
if (!list_empty(&tp->rx_done)) if (!list_empty(&tp->rx_done))
napi_schedule(napi); napi_schedule(napi);
else if (!skb_queue_empty(&tp->tx_queue) &&
!list_empty(&tp->tx_free))
napi_schedule(napi);
} }
out: out:
...@@ -2366,11 +2367,11 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, ...@@ -2366,11 +2367,11 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
if (!list_empty(&tp->tx_free)) { if (!list_empty(&tp->tx_free)) {
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
set_bit(SCHEDULE_NAPI, &tp->flags); set_bit(SCHEDULE_TASKLET, &tp->flags);
schedule_delayed_work(&tp->schedule, 0); schedule_delayed_work(&tp->schedule, 0);
} else { } else {
usb_mark_last_busy(tp->udev); usb_mark_last_busy(tp->udev);
napi_schedule(&tp->napi); tasklet_schedule(&tp->tx_tl);
} }
} else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen) { } else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen) {
netif_stop_queue(netdev); netif_stop_queue(netdev);
...@@ -4020,9 +4021,11 @@ static void set_carrier(struct r8152 *tp) ...@@ -4020,9 +4021,11 @@ static void set_carrier(struct r8152 *tp)
} else { } else {
if (netif_carrier_ok(netdev)) { if (netif_carrier_ok(netdev)) {
netif_carrier_off(netdev); netif_carrier_off(netdev);
tasklet_disable(&tp->tx_tl);
napi_disable(napi); napi_disable(napi);
tp->rtl_ops.disable(tp); tp->rtl_ops.disable(tp);
napi_enable(napi); napi_enable(napi);
tasklet_enable(&tp->tx_tl);
netif_info(tp, link, netdev, "carrier off\n"); netif_info(tp, link, netdev, "carrier off\n");
} }
} }
...@@ -4055,10 +4058,10 @@ static void rtl_work_func_t(struct work_struct *work) ...@@ -4055,10 +4058,10 @@ static void rtl_work_func_t(struct work_struct *work)
if (test_and_clear_bit(RTL8152_SET_RX_MODE, &tp->flags)) if (test_and_clear_bit(RTL8152_SET_RX_MODE, &tp->flags))
_rtl8152_set_rx_mode(tp->netdev); _rtl8152_set_rx_mode(tp->netdev);
/* don't schedule napi before linking */ /* don't schedule tasket before linking */
if (test_and_clear_bit(SCHEDULE_NAPI, &tp->flags) && if (test_and_clear_bit(SCHEDULE_TASKLET, &tp->flags) &&
netif_carrier_ok(tp->netdev)) netif_carrier_ok(tp->netdev))
napi_schedule(&tp->napi); tasklet_schedule(&tp->tx_tl);
mutex_unlock(&tp->control); mutex_unlock(&tp->control);
...@@ -4144,6 +4147,7 @@ static int rtl8152_open(struct net_device *netdev) ...@@ -4144,6 +4147,7 @@ static int rtl8152_open(struct net_device *netdev)
goto out_unlock; goto out_unlock;
} }
napi_enable(&tp->napi); napi_enable(&tp->napi);
tasklet_enable(&tp->tx_tl);
mutex_unlock(&tp->control); mutex_unlock(&tp->control);
...@@ -4171,6 +4175,7 @@ static int rtl8152_close(struct net_device *netdev) ...@@ -4171,6 +4175,7 @@ static int rtl8152_close(struct net_device *netdev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
unregister_pm_notifier(&tp->pm_notifier); unregister_pm_notifier(&tp->pm_notifier);
#endif #endif
tasklet_disable(&tp->tx_tl);
if (!test_bit(RTL8152_UNPLUG, &tp->flags)) if (!test_bit(RTL8152_UNPLUG, &tp->flags))
napi_disable(&tp->napi); napi_disable(&tp->napi);
clear_bit(WORK_ENABLE, &tp->flags); clear_bit(WORK_ENABLE, &tp->flags);
...@@ -4440,6 +4445,7 @@ static int rtl8152_pre_reset(struct usb_interface *intf) ...@@ -4440,6 +4445,7 @@ static int rtl8152_pre_reset(struct usb_interface *intf)
return 0; return 0;
netif_stop_queue(netdev); netif_stop_queue(netdev);
tasklet_disable(&tp->tx_tl);
napi_disable(&tp->napi); napi_disable(&tp->napi);
clear_bit(WORK_ENABLE, &tp->flags); clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb); usb_kill_urb(tp->intr_urb);
...@@ -4483,6 +4489,7 @@ static int rtl8152_post_reset(struct usb_interface *intf) ...@@ -4483,6 +4489,7 @@ static int rtl8152_post_reset(struct usb_interface *intf)
} }
napi_enable(&tp->napi); napi_enable(&tp->napi);
tasklet_enable(&tp->tx_tl);
netif_wake_queue(netdev); netif_wake_queue(netdev);
usb_submit_urb(tp->intr_urb, GFP_KERNEL); usb_submit_urb(tp->intr_urb, GFP_KERNEL);
...@@ -4636,10 +4643,12 @@ static int rtl8152_system_suspend(struct r8152 *tp) ...@@ -4636,10 +4643,12 @@ static int rtl8152_system_suspend(struct r8152 *tp)
clear_bit(WORK_ENABLE, &tp->flags); clear_bit(WORK_ENABLE, &tp->flags);
usb_kill_urb(tp->intr_urb); usb_kill_urb(tp->intr_urb);
tasklet_disable(&tp->tx_tl);
napi_disable(napi); napi_disable(napi);
cancel_delayed_work_sync(&tp->schedule); cancel_delayed_work_sync(&tp->schedule);
tp->rtl_ops.down(tp); tp->rtl_ops.down(tp);
napi_enable(napi); napi_enable(napi);
tasklet_enable(&tp->tx_tl);
} }
return 0; return 0;
...@@ -5499,6 +5508,8 @@ static int rtl8152_probe(struct usb_interface *intf, ...@@ -5499,6 +5508,8 @@ static int rtl8152_probe(struct usb_interface *intf,
mutex_init(&tp->control); mutex_init(&tp->control);
INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t);
tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp);
tasklet_disable(&tp->tx_tl);
netdev->netdev_ops = &rtl8152_netdev_ops; netdev->netdev_ops = &rtl8152_netdev_ops;
netdev->watchdog_timeo = RTL8152_TX_TIMEOUT; netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
...@@ -5585,6 +5596,7 @@ static int rtl8152_probe(struct usb_interface *intf, ...@@ -5585,6 +5596,7 @@ static int rtl8152_probe(struct usb_interface *intf,
out1: out1:
netif_napi_del(&tp->napi); netif_napi_del(&tp->napi);
tasklet_kill(&tp->tx_tl);
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
out: out:
free_netdev(netdev); free_netdev(netdev);
...@@ -5601,6 +5613,7 @@ static void rtl8152_disconnect(struct usb_interface *intf) ...@@ -5601,6 +5613,7 @@ static void rtl8152_disconnect(struct usb_interface *intf)
netif_napi_del(&tp->napi); netif_napi_del(&tp->napi);
unregister_netdev(tp->netdev); unregister_netdev(tp->netdev);
tasklet_kill(&tp->tx_tl);
cancel_delayed_work_sync(&tp->hw_phy_work); cancel_delayed_work_sync(&tp->hw_phy_work);
tp->rtl_ops.unload(tp); tp->rtl_ops.unload(tp);
free_netdev(tp->netdev); free_netdev(tp->netdev);
......
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