ipath_keys.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  3. *
  4. * This software is available to you under a choice of one of two
  5. * licenses. You may choose to be licensed under the terms of the GNU
  6. * General Public License (GPL) Version 2, available from the file
  7. * COPYING in the main directory of this source tree, or the
  8. * OpenIB.org BSD license below:
  9. *
  10. * Redistribution and use in source and binary forms, with or
  11. * without modification, are permitted provided that the following
  12. * conditions are met:
  13. *
  14. * - Redistributions of source code must retain the above
  15. * copyright notice, this list of conditions and the following
  16. * disclaimer.
  17. *
  18. * - Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials
  21. * provided with the distribution.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30. * SOFTWARE.
  31. */
  32. #include <asm/io.h>
  33. #include "ipath_verbs.h"
  34. /**
  35. * ipath_alloc_lkey - allocate an lkey
  36. * @rkt: lkey table in which to allocate the lkey
  37. * @mr: memory region that this lkey protects
  38. *
  39. * Returns 1 if successful, otherwise returns 0.
  40. */
  41. int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr)
  42. {
  43. unsigned long flags;
  44. u32 r;
  45. u32 n;
  46. int ret;
  47. spin_lock_irqsave(&rkt->lock, flags);
  48. /* Find the next available LKEY */
  49. r = n = rkt->next;
  50. for (;;) {
  51. if (rkt->table[r] == NULL)
  52. break;
  53. r = (r + 1) & (rkt->max - 1);
  54. if (r == n) {
  55. spin_unlock_irqrestore(&rkt->lock, flags);
  56. _VERBS_INFO("LKEY table full\n");
  57. ret = 0;
  58. goto bail;
  59. }
  60. }
  61. rkt->next = (r + 1) & (rkt->max - 1);
  62. /*
  63. * Make sure lkey is never zero which is reserved to indicate an
  64. * unrestricted LKEY.
  65. */
  66. rkt->gen++;
  67. mr->lkey = (r << (32 - ib_ipath_lkey_table_size)) |
  68. ((((1 << (24 - ib_ipath_lkey_table_size)) - 1) & rkt->gen)
  69. << 8);
  70. if (mr->lkey == 0) {
  71. mr->lkey |= 1 << 8;
  72. rkt->gen++;
  73. }
  74. rkt->table[r] = mr;
  75. spin_unlock_irqrestore(&rkt->lock, flags);
  76. ret = 1;
  77. bail:
  78. return ret;
  79. }
  80. /**
  81. * ipath_free_lkey - free an lkey
  82. * @rkt: table from which to free the lkey
  83. * @lkey: lkey id to free
  84. */
  85. void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
  86. {
  87. unsigned long flags;
  88. u32 r;
  89. if (lkey == 0)
  90. return;
  91. r = lkey >> (32 - ib_ipath_lkey_table_size);
  92. spin_lock_irqsave(&rkt->lock, flags);
  93. rkt->table[r] = NULL;
  94. spin_unlock_irqrestore(&rkt->lock, flags);
  95. }
  96. /**
  97. * ipath_lkey_ok - check IB SGE for validity and initialize
  98. * @rkt: table containing lkey to check SGE against
  99. * @isge: outgoing internal SGE
  100. * @sge: SGE to check
  101. * @acc: access flags
  102. *
  103. * Return 1 if valid and successful, otherwise returns 0.
  104. *
  105. * Check the IB SGE for validity and initialize our internal version
  106. * of it.
  107. */
  108. int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
  109. struct ib_sge *sge, int acc)
  110. {
  111. struct ipath_mregion *mr;
  112. size_t off;
  113. int ret;
  114. /*
  115. * We use LKEY == zero to mean a physical kmalloc() address.
  116. * This is a bit of a hack since we rely on dma_map_single()
  117. * being reversible by calling bus_to_virt().
  118. */
  119. if (sge->lkey == 0) {
  120. isge->mr = NULL;
  121. isge->vaddr = bus_to_virt(sge->addr);
  122. isge->length = sge->length;
  123. isge->sge_length = sge->length;
  124. ret = 1;
  125. goto bail;
  126. }
  127. mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
  128. if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
  129. ret = 0;
  130. goto bail;
  131. }
  132. off = sge->addr - mr->user_base;
  133. if (unlikely(sge->addr < mr->user_base ||
  134. off + sge->length > mr->length ||
  135. (mr->access_flags & acc) != acc)) {
  136. ret = 0;
  137. goto bail;
  138. }
  139. off += mr->offset;
  140. isge->mr = mr;
  141. isge->m = 0;
  142. isge->n = 0;
  143. while (off >= mr->map[isge->m]->segs[isge->n].length) {
  144. off -= mr->map[isge->m]->segs[isge->n].length;
  145. isge->n++;
  146. if (isge->n >= IPATH_SEGSZ) {
  147. isge->m++;
  148. isge->n = 0;
  149. }
  150. }
  151. isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
  152. isge->length = mr->map[isge->m]->segs[isge->n].length - off;
  153. isge->sge_length = sge->length;
  154. ret = 1;
  155. bail:
  156. return ret;
  157. }
  158. /**
  159. * ipath_rkey_ok - check the IB virtual address, length, and RKEY
  160. * @dev: infiniband device
  161. * @ss: SGE state
  162. * @len: length of data
  163. * @vaddr: virtual address to place data
  164. * @rkey: rkey to check
  165. * @acc: access flags
  166. *
  167. * Return 1 if successful, otherwise 0.
  168. */
  169. int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
  170. u32 len, u64 vaddr, u32 rkey, int acc)
  171. {
  172. struct ipath_lkey_table *rkt = &dev->lk_table;
  173. struct ipath_sge *sge = &ss->sge;
  174. struct ipath_mregion *mr;
  175. size_t off;
  176. int ret;
  177. mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
  178. if (unlikely(mr == NULL || mr->lkey != rkey)) {
  179. ret = 0;
  180. goto bail;
  181. }
  182. off = vaddr - mr->iova;
  183. if (unlikely(vaddr < mr->iova || off + len > mr->length ||
  184. (mr->access_flags & acc) == 0)) {
  185. ret = 0;
  186. goto bail;
  187. }
  188. off += mr->offset;
  189. sge->mr = mr;
  190. sge->m = 0;
  191. sge->n = 0;
  192. while (off >= mr->map[sge->m]->segs[sge->n].length) {
  193. off -= mr->map[sge->m]->segs[sge->n].length;
  194. sge->n++;
  195. if (sge->n >= IPATH_SEGSZ) {
  196. sge->m++;
  197. sge->n = 0;
  198. }
  199. }
  200. sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
  201. sge->length = mr->map[sge->m]->segs[sge->n].length - off;
  202. sge->sge_length = len;
  203. ss->sg_list = NULL;
  204. ss->num_sge = 1;
  205. ret = 1;
  206. bail:
  207. return ret;
  208. }