mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
thunderbolt: Make interrupt optional for rings
For some use-cases it does make sense to poll the rings directly instead of relying on the interrupt. For this reason add a new flag RING_FLAG_NO_INTERRUPT that can be used to allocate ring in polled mode. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
parent
42bc693533
commit
f5cb175ed7
|
|
@ -235,6 +235,12 @@ static void ring_write_descriptors(struct tb_ring *ring)
|
|||
{
|
||||
struct ring_frame *frame, *n;
|
||||
struct ring_desc *descriptor;
|
||||
u32 flags;
|
||||
|
||||
flags = RING_DESC_POSTED;
|
||||
if (!(ring->flags & RING_FLAG_NO_INTERRUPT))
|
||||
flags |= RING_DESC_INTERRUPT;
|
||||
|
||||
list_for_each_entry_safe(frame, n, &ring->queue, list) {
|
||||
if (ring_full(ring))
|
||||
break;
|
||||
|
|
@ -242,7 +248,7 @@ static void ring_write_descriptors(struct tb_ring *ring)
|
|||
descriptor = &ring->descriptors[ring->head];
|
||||
descriptor->phys = frame->buffer_phy;
|
||||
descriptor->time = 0;
|
||||
descriptor->flags = RING_DESC_POSTED | RING_DESC_INTERRUPT;
|
||||
descriptor->flags = flags;
|
||||
if (ring->is_tx) {
|
||||
descriptor->length = frame->size;
|
||||
descriptor->eof = frame->eof;
|
||||
|
|
@ -339,8 +345,9 @@ EXPORT_SYMBOL_GPL(__tb_ring_enqueue);
|
|||
* @ring: Ring to poll
|
||||
*
|
||||
* This function can be called when @start_poll callback of the @ring
|
||||
* has been called. It will read one completed frame from the ring and
|
||||
* return it to the caller.
|
||||
* has been called or the ring is created with %RING_FLAG_NO_INTERRUPT.
|
||||
* It will read one completed frame from the ring and return it to the
|
||||
* caller.
|
||||
*
|
||||
* Return: Pointer to &struct ring_frame, %NULL if there is no more
|
||||
* completed frames.
|
||||
|
|
@ -538,6 +545,12 @@ static struct tb_ring *tb_ring_alloc(struct tb_nhi *nhi, u32 hop, int size,
|
|||
dev_dbg(nhi->dev, "allocating %s ring %d of size %d\n",
|
||||
transmit ? "TX" : "RX", hop, size);
|
||||
|
||||
if ((flags & RING_FLAG_NO_INTERRUPT) && start_poll) {
|
||||
dev_WARN(nhi->dev,
|
||||
"start_poll() and NO_INTERRUPT cannot be used at the same time\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ring = kzalloc_obj(*ring);
|
||||
if (!ring)
|
||||
return NULL;
|
||||
|
|
@ -568,7 +581,7 @@ static struct tb_ring *tb_ring_alloc(struct tb_nhi *nhi, u32 hop, int size,
|
|||
if (!ring->descriptors)
|
||||
goto err_free_ring;
|
||||
|
||||
if (nhi->ops->request_ring_irq) {
|
||||
if (!(flags & RING_FLAG_NO_INTERRUPT) && nhi->ops->request_ring_irq) {
|
||||
if (nhi->ops->request_ring_irq(ring, flags & RING_FLAG_NO_SUSPEND))
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
|
@ -701,7 +714,8 @@ void tb_ring_start(struct tb_ring *ring)
|
|||
ring_iowrite32options(ring, flags, 0);
|
||||
}
|
||||
|
||||
ring_interrupt_active(ring, true);
|
||||
if (!(ring->flags & RING_FLAG_NO_INTERRUPT))
|
||||
ring_interrupt_active(ring, true);
|
||||
ring->running = true;
|
||||
err:
|
||||
spin_unlock(&ring->lock);
|
||||
|
|
@ -761,7 +775,8 @@ void tb_ring_stop(struct tb_ring *ring)
|
|||
RING_TYPE(ring), ring->hop);
|
||||
goto err;
|
||||
}
|
||||
ring_interrupt_active(ring, false);
|
||||
if (!(ring->flags & RING_FLAG_NO_INTERRUPT))
|
||||
ring_interrupt_active(ring, false);
|
||||
|
||||
ring_iowrite32options(ring, 0, 0);
|
||||
ring_iowrite64desc(ring, 0, 0);
|
||||
|
|
|
|||
|
|
@ -598,6 +598,8 @@ struct tb_ring {
|
|||
#define RING_FLAG_FRAME BIT(1)
|
||||
/* Enable end-to-end flow control */
|
||||
#define RING_FLAG_E2E BIT(2)
|
||||
/* Do not enable interrupt for the ring */
|
||||
#define RING_FLAG_NO_INTERRUPT BIT(3)
|
||||
|
||||
struct ring_frame;
|
||||
typedef void (*ring_cb)(struct tb_ring *, struct ring_frame *, bool canceled);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user