diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-05-07 01:07:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-07 01:07:48 -0400 |
commit | eecfd7c4e36ff532d895885971d01d049bd3e014 (patch) | |
tree | f75ee9904f29f9fd8d5a019766e41d3c07066903 | |
parent | 39e0786d3cf39c6d2f47b4818ae2da8b8ebc9ce2 (diff) |
rps: Various optimizations
Introduce ____napi_schedule() helper for callers in irq disabled
contexts. rps_trigger_softirq() becomes a leaf function.
Use container_of() in process_backlog() instead of accessing per_cpu
address.
Use a custom inlined version of __napi_complete() in process_backlog()
to avoid one locked instruction :
only current cpu owns and manipulates this napi,
and NAPI_STATE_SCHED is the only possible flag set on backlog.
we can use a plain write instead of clear_bit(),
and we dont need an smp_mb() memory barrier, since RPS is on,
backlog is protected by a spinlock.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/dev.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 36d53be4fca6..32611c8f1219 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2205,6 +2205,14 @@ int netdev_max_backlog __read_mostly = 1000; | |||
2205 | int netdev_budget __read_mostly = 300; | 2205 | int netdev_budget __read_mostly = 300; |
2206 | int weight_p __read_mostly = 64; /* old backlog weight */ | 2206 | int weight_p __read_mostly = 64; /* old backlog weight */ |
2207 | 2207 | ||
2208 | /* Called with irq disabled */ | ||
2209 | static inline void ____napi_schedule(struct softnet_data *sd, | ||
2210 | struct napi_struct *napi) | ||
2211 | { | ||
2212 | list_add_tail(&napi->poll_list, &sd->poll_list); | ||
2213 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
2214 | } | ||
2215 | |||
2208 | #ifdef CONFIG_RPS | 2216 | #ifdef CONFIG_RPS |
2209 | 2217 | ||
2210 | /* One global table that all flow-based protocols share. */ | 2218 | /* One global table that all flow-based protocols share. */ |
@@ -2363,7 +2371,7 @@ static void rps_trigger_softirq(void *data) | |||
2363 | { | 2371 | { |
2364 | struct softnet_data *sd = data; | 2372 | struct softnet_data *sd = data; |
2365 | 2373 | ||
2366 | __napi_schedule(&sd->backlog); | 2374 | ____napi_schedule(sd, &sd->backlog); |
2367 | sd->received_rps++; | 2375 | sd->received_rps++; |
2368 | } | 2376 | } |
2369 | 2377 | ||
@@ -2421,7 +2429,7 @@ enqueue: | |||
2421 | /* Schedule NAPI for backlog device */ | 2429 | /* Schedule NAPI for backlog device */ |
2422 | if (napi_schedule_prep(&sd->backlog)) { | 2430 | if (napi_schedule_prep(&sd->backlog)) { |
2423 | if (!rps_ipi_queued(sd)) | 2431 | if (!rps_ipi_queued(sd)) |
2424 | __napi_schedule(&sd->backlog); | 2432 | ____napi_schedule(sd, &sd->backlog); |
2425 | } | 2433 | } |
2426 | goto enqueue; | 2434 | goto enqueue; |
2427 | } | 2435 | } |
@@ -3280,7 +3288,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) | |||
3280 | static int process_backlog(struct napi_struct *napi, int quota) | 3288 | static int process_backlog(struct napi_struct *napi, int quota) |
3281 | { | 3289 | { |
3282 | int work = 0; | 3290 | int work = 0; |
3283 | struct softnet_data *sd = &__get_cpu_var(softnet_data); | 3291 | struct softnet_data *sd = container_of(napi, struct softnet_data, backlog); |
3284 | 3292 | ||
3285 | #ifdef CONFIG_RPS | 3293 | #ifdef CONFIG_RPS |
3286 | /* Check if we have pending ipi, its better to send them now, | 3294 | /* Check if we have pending ipi, its better to send them now, |
@@ -3313,7 +3321,16 @@ static int process_backlog(struct napi_struct *napi, int quota) | |||
3313 | &sd->process_queue); | 3321 | &sd->process_queue); |
3314 | } | 3322 | } |
3315 | if (qlen < quota - work) { | 3323 | if (qlen < quota - work) { |
3316 | __napi_complete(napi); | 3324 | /* |
3325 | * Inline a custom version of __napi_complete(). | ||
3326 | * only current cpu owns and manipulates this napi, | ||
3327 | * and NAPI_STATE_SCHED is the only possible flag set on backlog. | ||
3328 | * we can use a plain write instead of clear_bit(), | ||
3329 | * and we dont need an smp_mb() memory barrier. | ||
3330 | */ | ||
3331 | list_del(&napi->poll_list); | ||
3332 | napi->state = 0; | ||
3333 | |||
3317 | quota = work + qlen; | 3334 | quota = work + qlen; |
3318 | } | 3335 | } |
3319 | rps_unlock(sd); | 3336 | rps_unlock(sd); |
@@ -3334,8 +3351,7 @@ void __napi_schedule(struct napi_struct *n) | |||
3334 | unsigned long flags; | 3351 | unsigned long flags; |
3335 | 3352 | ||
3336 | local_irq_save(flags); | 3353 | local_irq_save(flags); |
3337 | list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list); | 3354 | ____napi_schedule(&__get_cpu_var(softnet_data), n); |
3338 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
3339 | local_irq_restore(flags); | 3355 | local_irq_restore(flags); |
3340 | } | 3356 | } |
3341 | EXPORT_SYMBOL(__napi_schedule); | 3357 | EXPORT_SYMBOL(__napi_schedule); |