adm5120-mem.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * ADM5120 HCD (Host Controller Driver) for USB
  3. *
  4. * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
  5. *
  6. * This file was derived from: drivers/usb/host/ohci-mem.c
  7. * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
  8. * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License version 2 as published
  12. * by the Free Software Foundation.
  13. *
  14. */
  15. /*-------------------------------------------------------------------------*/
  16. /*
  17. * OHCI deals with three types of memory:
  18. * - data used only by the HCD ... kmalloc is fine
  19. * - async and periodic schedules, shared by HC and HCD ... these
  20. * need to use dma_pool or dma_alloc_coherent
  21. * - driver buffers, read/written by HC ... the hcd glue or the
  22. * device driver provides us with dma addresses
  23. *
  24. * There's also "register" data, which is memory mapped.
  25. * No memory seen by this driver (or any HCD) may be paged out.
  26. */
  27. /*-------------------------------------------------------------------------*/
  28. static void admhc_hcd_init(struct admhcd *ahcd)
  29. {
  30. ahcd->next_statechange = jiffies;
  31. spin_lock_init(&ahcd->lock);
  32. INIT_LIST_HEAD(&ahcd->pending);
  33. }
  34. /*-------------------------------------------------------------------------*/
  35. static int admhc_mem_init(struct admhcd *ahcd)
  36. {
  37. ahcd->td_cache = dma_pool_create("admhc_td",
  38. admhcd_to_hcd(ahcd)->self.controller,
  39. sizeof(struct td),
  40. TD_ALIGN, /* byte alignment */
  41. 0 /* no page-crossing issues */
  42. );
  43. if (!ahcd->td_cache)
  44. goto err;
  45. ahcd->ed_cache = dma_pool_create("admhc_ed",
  46. admhcd_to_hcd(ahcd)->self.controller,
  47. sizeof(struct ed),
  48. ED_ALIGN, /* byte alignment */
  49. 0 /* no page-crossing issues */
  50. );
  51. if (!ahcd->ed_cache)
  52. goto err_td_cache;
  53. return 0;
  54. err_td_cache:
  55. dma_pool_destroy(ahcd->td_cache);
  56. ahcd->td_cache = NULL;
  57. err:
  58. return -ENOMEM;
  59. }
  60. static void admhc_mem_cleanup(struct admhcd *ahcd)
  61. {
  62. if (ahcd->td_cache) {
  63. dma_pool_destroy(ahcd->td_cache);
  64. ahcd->td_cache = NULL;
  65. }
  66. if (ahcd->ed_cache) {
  67. dma_pool_destroy(ahcd->ed_cache);
  68. ahcd->ed_cache = NULL;
  69. }
  70. }
  71. /*-------------------------------------------------------------------------*/
  72. /* ahcd "done list" processing needs this mapping */
  73. static inline struct td *dma_to_td(struct admhcd *ahcd, dma_addr_t td_dma)
  74. {
  75. struct td *td;
  76. td_dma &= TD_MASK;
  77. td = ahcd->td_hash[TD_HASH_FUNC(td_dma)];
  78. while (td && td->td_dma != td_dma)
  79. td = td->td_hash;
  80. return td;
  81. }
  82. /* TDs ... */
  83. static struct td *td_alloc(struct admhcd *ahcd, gfp_t mem_flags)
  84. {
  85. dma_addr_t dma;
  86. struct td *td;
  87. td = dma_pool_alloc(ahcd->td_cache, mem_flags, &dma);
  88. if (!td)
  89. return NULL;
  90. /* in case ahcd fetches it, make it look dead */
  91. memset(td, 0, sizeof *td);
  92. td->hwNextTD = cpu_to_hc32(ahcd, dma);
  93. td->td_dma = dma;
  94. /* hashed in td_fill */
  95. return td;
  96. }
  97. static void td_free(struct admhcd *ahcd, struct td *td)
  98. {
  99. struct td **prev = &ahcd->td_hash[TD_HASH_FUNC(td->td_dma)];
  100. while (*prev && *prev != td)
  101. prev = &(*prev)->td_hash;
  102. if (*prev)
  103. *prev = td->td_hash;
  104. #if 0
  105. /* TODO: remove */
  106. else if ((td->hwINFO & cpu_to_hc32(ahcd, TD_DONE)) != 0)
  107. admhc_dbg(ahcd, "no hash for td %p\n", td);
  108. #else
  109. else if ((td->flags & TD_FLAG_DONE) != 0)
  110. admhc_dbg(ahcd, "no hash for td %p\n", td);
  111. #endif
  112. dma_pool_free(ahcd->td_cache, td, td->td_dma);
  113. }
  114. /*-------------------------------------------------------------------------*/
  115. /* EDs ... */
  116. static struct ed *ed_alloc(struct admhcd *ahcd, gfp_t mem_flags)
  117. {
  118. dma_addr_t dma;
  119. struct ed *ed;
  120. ed = dma_pool_alloc(ahcd->ed_cache, mem_flags, &dma);
  121. if (!ed)
  122. return NULL;
  123. memset(ed, 0, sizeof(*ed));
  124. ed->dma = dma;
  125. INIT_LIST_HEAD(&ed->td_list);
  126. INIT_LIST_HEAD(&ed->urb_list);
  127. return ed;
  128. }
  129. static void ed_free(struct admhcd *ahcd, struct ed *ed)
  130. {
  131. dma_pool_free(ahcd->ed_cache, ed, ed->dma);
  132. }
  133. /*-------------------------------------------------------------------------*/
  134. /* URB priv ... */
  135. static void urb_priv_free(struct admhcd *ahcd, struct urb_priv *urb_priv)
  136. {
  137. int i;
  138. for (i = 0; i < urb_priv->td_cnt; i++)
  139. if (urb_priv->td[i])
  140. td_free(ahcd, urb_priv->td[i]);
  141. list_del(&urb_priv->pending);
  142. kfree(urb_priv);
  143. }
  144. static struct urb_priv *urb_priv_alloc(struct admhcd *ahcd, int num_tds,
  145. gfp_t mem_flags)
  146. {
  147. struct urb_priv *priv;
  148. /* allocate the private part of the URB */
  149. priv = kzalloc(sizeof(*priv) + sizeof(struct td) * num_tds, mem_flags);
  150. if (!priv)
  151. goto err;
  152. /* allocate the TDs (deferring hash chain updates) */
  153. for (priv->td_cnt = 0; priv->td_cnt < num_tds; priv->td_cnt++) {
  154. priv->td[priv->td_cnt] = td_alloc(ahcd, mem_flags);
  155. if (priv->td[priv->td_cnt] == NULL)
  156. goto err_free;
  157. }
  158. INIT_LIST_HEAD(&priv->pending);
  159. return priv;
  160. err_free:
  161. urb_priv_free(ahcd, priv);
  162. err:
  163. return NULL;
  164. }