Lines Matching +full:low +full:- +full:bandwidth

1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * - Isochronous DMA context management
5 * - Isochronous bus resource management (channels, bandwidth), client side
10 #include <linux/dma-mapping.h>
13 #include <linux/firewire-constants.h>
35 buffer->page_count = 0; in fw_iso_buffer_alloc()
36 buffer->page_count_mapped = 0; in fw_iso_buffer_alloc()
37 buffer->pages = kmalloc_array(page_count, sizeof(buffer->pages[0]), in fw_iso_buffer_alloc()
39 if (buffer->pages == NULL) in fw_iso_buffer_alloc()
40 return -ENOMEM; in fw_iso_buffer_alloc()
43 buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); in fw_iso_buffer_alloc()
44 if (buffer->pages[i] == NULL) in fw_iso_buffer_alloc()
47 buffer->page_count = i; in fw_iso_buffer_alloc()
50 return -ENOMEM; in fw_iso_buffer_alloc()
62 buffer->direction = direction; in fw_iso_buffer_map_dma()
64 for (i = 0; i < buffer->page_count; i++) { in fw_iso_buffer_map_dma()
65 address = dma_map_page(card->device, buffer->pages[i], in fw_iso_buffer_map_dma()
67 if (dma_mapping_error(card->device, address)) in fw_iso_buffer_map_dma()
70 set_page_private(buffer->pages[i], address); in fw_iso_buffer_map_dma()
72 buffer->page_count_mapped = i; in fw_iso_buffer_map_dma()
73 if (i < buffer->page_count) in fw_iso_buffer_map_dma()
74 return -ENOMEM; in fw_iso_buffer_map_dma()
102 for (i = 0; i < buffer->page_count_mapped; i++) { in fw_iso_buffer_destroy()
103 address = page_private(buffer->pages[i]); in fw_iso_buffer_destroy()
104 dma_unmap_page(card->device, address, in fw_iso_buffer_destroy()
105 PAGE_SIZE, buffer->direction); in fw_iso_buffer_destroy()
107 for (i = 0; i < buffer->page_count; i++) in fw_iso_buffer_destroy()
108 __free_page(buffer->pages[i]); in fw_iso_buffer_destroy()
110 kfree(buffer->pages); in fw_iso_buffer_destroy()
111 buffer->pages = NULL; in fw_iso_buffer_destroy()
112 buffer->page_count = 0; in fw_iso_buffer_destroy()
113 buffer->page_count_mapped = 0; in fw_iso_buffer_destroy()
124 for (i = 0; i < buffer->page_count; i++) { in fw_iso_buffer_lookup()
125 address = page_private(buffer->pages[i]); in fw_iso_buffer_lookup()
126 offset = (ssize_t)completed - (ssize_t)address; in fw_iso_buffer_lookup()
140 ctx = card->driver->allocate_iso_context(card, in fw_iso_context_create()
145 ctx->card = card; in fw_iso_context_create()
146 ctx->type = type; in fw_iso_context_create()
147 ctx->channel = channel; in fw_iso_context_create()
148 ctx->speed = speed; in fw_iso_context_create()
149 ctx->header_size = header_size; in fw_iso_context_create()
150 ctx->callback.sc = callback; in fw_iso_context_create()
151 ctx->callback_data = callback_data; in fw_iso_context_create()
167 ctx->card->driver->free_iso_context(ctx); in fw_iso_context_destroy()
178 return ctx->card->driver->start_iso(ctx, cycle, sync, tags); in fw_iso_context_start()
186 return ctx->card->driver->set_iso_channels(ctx, channels); in fw_iso_context_set_channels()
198 return ctx->card->driver->queue_iso(ctx, packet, buffer, payload); in fw_iso_context_queue()
208 ctx->card->driver->flush_queue_iso(ctx); in fw_iso_context_queue_flush()
213 * fw_iso_context_flush_completions() - process isochronous context in current process context.
237 if (WARN_ON_ONCE(current_work() == &ctx->work)) in fw_iso_context_flush_completions()
240 disable_work_sync(&ctx->work); in fw_iso_context_flush_completions()
242 err = ctx->card->driver->flush_iso_completions(ctx); in fw_iso_context_flush_completions()
244 enable_work(&ctx->work); in fw_iso_context_flush_completions()
261 if (WARN_ON_ONCE(current_work() == &ctx->work)) in fw_iso_context_stop()
264 err = ctx->card->driver->stop_iso(ctx); in fw_iso_context_stop()
266 cancel_work_sync(&ctx->work); in fw_iso_context_stop()
273 * Isochronous bus resource management (channels, bandwidth), client side
277 int bandwidth, bool allocate) in manage_bandwidth() argument
283 * On a 1394a IRM with low contention, try < 1 is enough. in manage_bandwidth()
284 * On a 1394-1995 IRM, we need at least try < 2. in manage_bandwidth()
288 new = allocate ? old - bandwidth : old + bandwidth; in manage_bandwidth()
290 return -EBUSY; in manage_bandwidth()
299 /* A generation change frees all bandwidth. */ in manage_bandwidth()
300 return allocate ? -EAGAIN : bandwidth; in manage_bandwidth()
304 return bandwidth; in manage_bandwidth()
311 return -EIO; in manage_bandwidth()
319 int channel, ret = -EIO, retry = 5; in manage_channel()
327 ret = -EBUSY; in manage_channel()
329 bit = cpu_to_be32(1 << (31 - channel)); in manage_channel()
340 return allocate ? -EAGAIN : channel; in manage_channel()
348 /* Is the IRM 1394a-2000 compliant? */ in manage_channel()
352 fallthrough; /* It's a 1394-1995 IRM, retry */ in manage_channel()
355 retry--; in manage_channel()
356 channel--; in manage_channel()
358 ret = -EIO; in manage_channel()
372 mask = channel < 32 ? 1 << channel : 1 << (channel - 32); in deallocate_channel()
380 * fw_iso_resource_manage() - Allocate or deallocate a channel and/or bandwidth
385 * @bandwidth: pointer for returning bandwidth allocation result
388 * In parameters: card, generation, channels_mask, bandwidth, allocate
389 * Out parameters: channel, bandwidth
395 * (Note, the IRM's CHANNELS_AVAILABLE is a big-endian bitfield with MSB for
397 * Allocates or deallocates as many bandwidth allocation units as specified.
400 * Returns bandwidth = 0 if no bandwidth was allocated or deallocated.
403 * channel = -EAGAIN.
405 * If channel allocation fails, no bandwidth will be allocated either.
406 * If bandwidth allocation fails, no channel will be allocated either.
407 * But deallocations of channel and bandwidth are tried independently
411 u64 channels_mask, int *channel, int *bandwidth, in fw_iso_resource_manage() argument
416 int irm_id, ret, c = -EINVAL; in fw_iso_resource_manage()
418 scoped_guard(spinlock_irq, &card->lock) in fw_iso_resource_manage()
419 irm_id = card->irm_node->node_id; in fw_iso_resource_manage()
435 *bandwidth = 0; in fw_iso_resource_manage()
437 if (*bandwidth == 0) in fw_iso_resource_manage()
440 ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); in fw_iso_resource_manage()
442 *bandwidth = 0; in fw_iso_resource_manage()