• Ahmed S. Darwish's avatar
    can: kvaser_usb: Fix tx queue start/stop race conditions · 8d3b73c0
    Ahmed S. Darwish authored
    commit a9dc960c upstream.
    
    A number of tx queue wake-up events went missing due to the
    outlined scenario below. Start state is a pool of 16 tx URBs,
    active tx_urbs count = 15, with the netdev tx queue open.
    
    CPU #1 [softirq]                         CPU #2 [softirq]
    start_xmit()                             tx_acknowledge()
    ................                         ................
    
    atomic_inc(&tx_urbs);
    if (atomic_read(&tx_urbs) >= 16) {
                            -->
                                             atomic_dec(&tx_urbs);
                                             netif_wake_queue();
                                             return;
                            <--
        netif_stop_queue();
    }
    
    At the end, the correct state expected is a 15 tx_urbs count
    value with the tx queue state _open_. Due to the race, we get
    the same tx_urbs value but with the tx queue state _stopped_.
    The wake-up event is completely lost.
    
    Thus avoid hand-rolled concurrency mechanisms and use a proper
    lock for contexts and tx queue protection.
    Signed-off-by: default avatarAhmed S. Darwish <ahmed.darwish@valeo.com>
    Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
    [ luis: backported to 3.16: adjusted context ]
    Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
    Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
    8d3b73c0
kvaser_usb.c 39.5 KB