fw-iso.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* -*- c-basic-offset: 8 -*-
  2. *
  3. * fw-iso.c - Isochronous IO
  4. * Copyright (C) 2006 Kristian Hoegsberg <krh@bitplanet.net>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/module.h>
  22. #include <linux/dma-mapping.h>
  23. #include <linux/vmalloc.h>
  24. #include <linux/mm.h>
  25. #include "fw-transaction.h"
  26. #include "fw-topology.h"
  27. #include "fw-device.h"
  28. static int
  29. setup_iso_buffer(struct fw_iso_context *ctx, size_t size,
  30. enum dma_data_direction direction)
  31. {
  32. struct page *page;
  33. int i, j;
  34. void *p;
  35. ctx->buffer_size = PAGE_ALIGN(size);
  36. if (size == 0)
  37. return 0;
  38. ctx->buffer = vmalloc_32_user(ctx->buffer_size);
  39. if (ctx->buffer == NULL)
  40. goto fail_buffer_alloc;
  41. ctx->page_count = ctx->buffer_size >> PAGE_SHIFT;
  42. ctx->pages =
  43. kzalloc(ctx->page_count * sizeof(ctx->pages[0]), GFP_KERNEL);
  44. if (ctx->pages == NULL)
  45. goto fail_pages_alloc;
  46. p = ctx->buffer;
  47. for (i = 0; i < ctx->page_count; i++, p += PAGE_SIZE) {
  48. page = vmalloc_to_page(p);
  49. ctx->pages[i] = dma_map_page(ctx->card->device,
  50. page, 0, PAGE_SIZE, direction);
  51. if (dma_mapping_error(ctx->pages[i]))
  52. goto fail_mapping;
  53. }
  54. return 0;
  55. fail_mapping:
  56. for (j = 0; j < i; j++)
  57. dma_unmap_page(ctx->card->device, ctx->pages[j],
  58. PAGE_SIZE, DMA_TO_DEVICE);
  59. fail_pages_alloc:
  60. vfree(ctx->buffer);
  61. fail_buffer_alloc:
  62. return -ENOMEM;
  63. }
  64. static void destroy_iso_buffer(struct fw_iso_context *ctx)
  65. {
  66. int i;
  67. for (i = 0; i < ctx->page_count; i++)
  68. dma_unmap_page(ctx->card->device, ctx->pages[i],
  69. PAGE_SIZE, DMA_TO_DEVICE);
  70. kfree(ctx->pages);
  71. vfree(ctx->buffer);
  72. }
  73. struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type,
  74. size_t buffer_size,
  75. fw_iso_callback_t callback,
  76. void *callback_data)
  77. {
  78. struct fw_iso_context *ctx;
  79. int retval;
  80. ctx = card->driver->allocate_iso_context(card, type);
  81. if (IS_ERR(ctx))
  82. return ctx;
  83. ctx->card = card;
  84. ctx->type = type;
  85. ctx->callback = callback;
  86. ctx->callback_data = callback_data;
  87. retval = setup_iso_buffer(ctx, buffer_size, DMA_TO_DEVICE);
  88. if (retval < 0) {
  89. card->driver->free_iso_context(ctx);
  90. return ERR_PTR(retval);
  91. }
  92. return ctx;
  93. }
  94. EXPORT_SYMBOL(fw_iso_context_create);
  95. void fw_iso_context_destroy(struct fw_iso_context *ctx)
  96. {
  97. struct fw_card *card = ctx->card;
  98. destroy_iso_buffer(ctx);
  99. card->driver->free_iso_context(ctx);
  100. }
  101. EXPORT_SYMBOL(fw_iso_context_destroy);
  102. int
  103. fw_iso_context_send(struct fw_iso_context *ctx,
  104. int channel, int speed, int cycle)
  105. {
  106. ctx->channel = channel;
  107. ctx->speed = speed;
  108. return ctx->card->driver->send_iso(ctx, cycle);
  109. }
  110. EXPORT_SYMBOL(fw_iso_context_send);
  111. int
  112. fw_iso_context_queue(struct fw_iso_context *ctx,
  113. struct fw_iso_packet *packet, void *payload)
  114. {
  115. struct fw_card *card = ctx->card;
  116. return card->driver->queue_iso(ctx, packet, payload);
  117. }
  118. EXPORT_SYMBOL(fw_iso_context_queue);