• Cyrille Pitchen's avatar
    net/macb: add TX multiqueue support for gem · 02c958dd
    Cyrille Pitchen authored
    gem devices designed with multiqueue CANNOT work without this patch.
    
    When probing a gem device, the driver must first prepare and enable the
    peripheral clock before accessing I/O registers. The second step is to read the
    MID register to find whether the device is a gem or an old macb IP.
    For gem devices, it reads the Design Configuration Register 6 (DCFG6) to
    compute to total number of queues, whereas macb devices always have a single
    queue.
    Only then it can call alloc_etherdev_mq() with the correct number of queues.
    This is the reason why the order of some initializations has been changed in
    macb_probe().
    Eventually, the dedicated IRQ and TX ring buffer descriptors are initialized
    for each queue.
    
    For backward compatibility reasons, queue0 uses the legacy registers ISR, IER,
    IDR, IMR, TBQP and RBQP. On the other hand, the other queues use new registers
    ISR[1..7], IER[1..7], IDR[1..7], IMR[1..7], TBQP[1..7] and RBQP[1..7].
    Except this hardware detail there is no real difference between queue0 and the
    others. The driver hides that thanks to the struct macb_queue.
    This structure allows us to share a common set of functions for all the queues.
    
    Besides when a TX error occurs, the gem MUST be halted before writing any of
    the TBQP registers to reset the relevant queue. An immediate side effect is
    that the other queues too aren't processed anymore by the gem.
    So macb_tx_error_task() calls netif_tx_stop_all_queues() to notify the Linux
    network engine that all transmissions are stopped.
    
    Also macb_tx_error_task() now calls spin_lock_irqsave() to prevent the
    interrupt handlers of the other queues from running as each of them may wake
    its associated queue up (please refer to macb_tx_interrupt()).
    
    Finally, as all queues have previously been stopped, they should be restarted
    calling netif_tx_start_all_queues() and setting the TSTART bit into the Network
    Control Register. Before this patch, when dealing with a single queue, the
    driver used to defer the reset of the faulting queue and the write of the
    TSTART bit until the next call of macb_start_xmit().
    As explained before, this bit is now set by macb_tx_error_task() too. That's
    why the faulting queue MUST be reset by setting the TX_USED bit in its first
    buffer descriptor before writing the TSTART bit.
    
    Queue 0 always exits and is the lowest priority when other queues are available.
    The higher the index of the queue is, the higher its priority is.
    
    When transmitting frames, the TX queue is selected by the skb->queue_mapping
    value. So queue discipline can be used to define the queue priority policy.
    Signed-off-by: default avatarCyrille Pitchen <cyrille.pitchen@atmel.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    02c958dd
macb.c 61.5 KB