pktgen: better scheduler friendliness

Previous update did not resched in inner loop causing watchdogs.
Rewrite inner loop to:
* account for delays better with less clock calls
* more accurate timing of delay:
- only delay if packet was successfully sent
- if delay is 100ns and it takes 10ns to build packet then
account for that
* use wait_event_interruptible_timeout rather than open coding it.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Stephen Hemminger and committed by
David S. Miller
ef87979c 6b80d6a6

+74 -81
+74 -81
net/core/pktgen.c
··· 2104 2104 2105 2105 static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) 2106 2106 { 2107 - ktime_t start; 2107 + ktime_t start_time, end_time; 2108 2108 s32 remaining; 2109 2109 struct hrtimer_sleeper t; 2110 2110 ··· 2115 2115 if (remaining <= 0) 2116 2116 return; 2117 2117 2118 - start = ktime_now(); 2118 + start_time = ktime_now(); 2119 2119 if (remaining < 100) 2120 2120 udelay(remaining); /* really small just spin */ 2121 2121 else { ··· 2134 2134 } while (t.task && pkt_dev->running && !signal_pending(current)); 2135 2135 __set_current_state(TASK_RUNNING); 2136 2136 } 2137 - pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start)); 2137 + end_time = ktime_now(); 2138 + 2139 + pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time)); 2140 + pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay); 2138 2141 } 2139 2142 2140 2143 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) ··· 3367 3364 mutex_unlock(&pktgen_thread_lock); 3368 3365 } 3369 3366 3370 - static void idle(struct pktgen_dev *pkt_dev) 3367 + static void pktgen_resched(struct pktgen_dev *pkt_dev) 3371 3368 { 3372 3369 ktime_t idle_start = ktime_now(); 3373 - 3374 - if (need_resched()) 3375 - schedule(); 3376 - else 3377 - cpu_relax(); 3378 - 3370 + schedule(); 3379 3371 pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); 3380 3372 } 3381 3373 3374 + static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev) 3375 + { 3376 + ktime_t idle_start = ktime_now(); 3377 + 3378 + while (atomic_read(&(pkt_dev->skb->users)) != 1) { 3379 + if (signal_pending(current)) 3380 + break; 3381 + 3382 + if (need_resched()) 3383 + pktgen_resched(pkt_dev); 3384 + else 3385 + cpu_relax(); 3386 + } 3387 + pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); 3388 + } 3382 3389 3383 3390 static void pktgen_xmit(struct pktgen_dev *pkt_dev) 3384 3391 { ··· 3399 3386 u16 queue_map; 3400 3387 int ret; 3401 3388 3402 - if (pkt_dev->delay) { 3403 - spin(pkt_dev, pkt_dev->next_tx); 3404 - 3405 - /* This is max DELAY, this has special meaning of 3406 - * "never transmit" 3407 - */ 3408 - if (pkt_dev->delay == ULLONG_MAX) { 3409 - pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX); 3410 - return; 3411 - } 3412 - } 3413 - 3414 - if (!pkt_dev->skb) { 3415 - set_cur_queue_map(pkt_dev); 3416 - queue_map = pkt_dev->cur_queue_map; 3417 - } else { 3418 - queue_map = skb_get_queue_mapping(pkt_dev->skb); 3419 - } 3420 - 3421 - txq = netdev_get_tx_queue(odev, queue_map); 3422 - /* Did we saturate the queue already? */ 3423 - if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) { 3424 - /* If device is down, then all queues are permnantly frozen */ 3425 - if (netif_running(odev)) 3426 - idle(pkt_dev); 3427 - else 3428 - pktgen_stop_device(pkt_dev); 3389 + /* If device is offline, then don't send */ 3390 + if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) { 3391 + pktgen_stop_device(pkt_dev); 3429 3392 return; 3430 3393 } 3431 3394 3395 + /* This is max DELAY, this has special meaning of 3396 + * "never transmit" 3397 + */ 3398 + if (unlikely(pkt_dev->delay == ULLONG_MAX)) { 3399 + pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX); 3400 + return; 3401 + } 3402 + 3403 + /* If no skb or clone count exhausted then get new one */ 3432 3404 if (!pkt_dev->skb || (pkt_dev->last_ok && 3433 3405 ++pkt_dev->clone_count >= pkt_dev->clone_skb)) { 3434 3406 /* build a new pkt */ ··· 3432 3434 pkt_dev->clone_count = 0; /* reset counter */ 3433 3435 } 3434 3436 3435 - /* fill_packet() might have changed the queue */ 3437 + if (pkt_dev->delay && pkt_dev->last_ok) 3438 + spin(pkt_dev, pkt_dev->next_tx); 3439 + 3436 3440 queue_map = skb_get_queue_mapping(pkt_dev->skb); 3437 3441 txq = netdev_get_tx_queue(odev, queue_map); 3438 3442 3439 3443 __netif_tx_lock_bh(txq); 3444 + atomic_inc(&(pkt_dev->skb->users)); 3445 + 3440 3446 if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) 3441 - pkt_dev->last_ok = 0; 3442 - else { 3443 - atomic_inc(&(pkt_dev->skb->users)); 3444 - 3445 - retry_now: 3447 + ret = NETDEV_TX_BUSY; 3448 + else 3446 3449 ret = (*xmit)(pkt_dev->skb, odev); 3447 - switch (ret) { 3448 - case NETDEV_TX_OK: 3449 - txq_trans_update(txq); 3450 - pkt_dev->last_ok = 1; 3451 - pkt_dev->sofar++; 3452 - pkt_dev->seq_num++; 3453 - pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; 3454 - break; 3455 - case NETDEV_TX_LOCKED: 3456 - cpu_relax(); 3457 - goto retry_now; 3458 - default: /* Drivers are not supposed to return other values! */ 3459 - if (net_ratelimit()) 3460 - pr_info("pktgen: %s xmit error: %d\n", 3461 - odev->name, ret); 3462 - pkt_dev->errors++; 3463 - /* fallthru */ 3464 - case NETDEV_TX_BUSY: 3465 - /* Retry it next time */ 3466 - atomic_dec(&(pkt_dev->skb->users)); 3467 - pkt_dev->last_ok = 0; 3468 - } 3469 3450 3470 - if (pkt_dev->delay) 3471 - pkt_dev->next_tx = ktime_add_ns(ktime_now(), 3472 - pkt_dev->delay); 3451 + switch (ret) { 3452 + case NETDEV_TX_OK: 3453 + txq_trans_update(txq); 3454 + pkt_dev->last_ok = 1; 3455 + pkt_dev->sofar++; 3456 + pkt_dev->seq_num++; 3457 + pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; 3458 + break; 3459 + default: /* Drivers are not supposed to return other values! */ 3460 + if (net_ratelimit()) 3461 + pr_info("pktgen: %s xmit error: %d\n", 3462 + odev->name, ret); 3463 + pkt_dev->errors++; 3464 + /* fallthru */ 3465 + case NETDEV_TX_LOCKED: 3466 + case NETDEV_TX_BUSY: 3467 + /* Retry it next time */ 3468 + atomic_dec(&(pkt_dev->skb->users)); 3469 + pkt_dev->last_ok = 0; 3473 3470 } 3474 3471 __netif_tx_unlock_bh(txq); 3475 3472 3476 3473 /* If pkt_dev->count is zero, then run forever */ 3477 3474 if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { 3478 - while (atomic_read(&(pkt_dev->skb->users)) != 1) { 3479 - if (signal_pending(current)) 3480 - break; 3481 - idle(pkt_dev); 3482 - } 3475 + pktgen_wait_for_skb(pkt_dev); 3483 3476 3484 3477 /* Done with this */ 3485 3478 pktgen_stop_device(pkt_dev); ··· 3503 3514 while (!kthread_should_stop()) { 3504 3515 pkt_dev = next_to_run(t); 3505 3516 3506 - if (!pkt_dev && 3507 - (t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV)) 3508 - == 0) { 3509 - prepare_to_wait(&(t->queue), &wait, 3510 - TASK_INTERRUPTIBLE); 3511 - schedule_timeout(HZ / 10); 3512 - finish_wait(&(t->queue), &wait); 3517 + if (unlikely(!pkt_dev && t->control == 0)) { 3518 + wait_event_interruptible_timeout(t->queue, 3519 + t->control != 0, 3520 + HZ/10); 3521 + continue; 3513 3522 } 3514 3523 3515 3524 __set_current_state(TASK_RUNNING); 3516 3525 3517 - if (pkt_dev) 3526 + if (likely(pkt_dev)) { 3518 3527 pktgen_xmit(pkt_dev); 3528 + 3529 + if (need_resched()) 3530 + pktgen_resched(pkt_dev); 3531 + else 3532 + cpu_relax(); 3533 + } 3519 3534 3520 3535 if (t->control & T_STOP) { 3521 3536 pktgen_stop(t);