safexcel_ring.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (C) 2017 Marvell
  3. *
  4. * Antoine Tenart <antoine.tenart@free-electrons.com>
  5. *
  6. * This file is licensed under the terms of the GNU General Public
  7. * License version 2. This program is licensed "as is" without any
  8. * warranty of any kind, whether express or implied.
  9. */
  10. #include <linux/dma-mapping.h>
  11. #include <linux/spinlock.h>
  12. #include "safexcel.h"
  13. int safexcel_init_ring_descriptors(struct safexcel_crypto_priv *priv,
  14. struct safexcel_ring *cdr,
  15. struct safexcel_ring *rdr)
  16. {
  17. cdr->offset = sizeof(u32) * priv->config.cd_offset;
  18. cdr->base = dmam_alloc_coherent(priv->dev,
  19. cdr->offset * EIP197_DEFAULT_RING_SIZE,
  20. &cdr->base_dma, GFP_KERNEL);
  21. if (!cdr->base)
  22. return -ENOMEM;
  23. cdr->write = cdr->base;
  24. cdr->base_end = cdr->base + cdr->offset * EIP197_DEFAULT_RING_SIZE;
  25. cdr->read = cdr->base;
  26. rdr->offset = sizeof(u32) * priv->config.rd_offset;
  27. rdr->base = dmam_alloc_coherent(priv->dev,
  28. rdr->offset * EIP197_DEFAULT_RING_SIZE,
  29. &rdr->base_dma, GFP_KERNEL);
  30. if (!rdr->base)
  31. return -ENOMEM;
  32. rdr->write = rdr->base;
  33. rdr->base_end = rdr->base + rdr->offset * EIP197_DEFAULT_RING_SIZE;
  34. rdr->read = rdr->base;
  35. return 0;
  36. }
  37. inline int safexcel_select_ring(struct safexcel_crypto_priv *priv)
  38. {
  39. return (atomic_inc_return(&priv->ring_used) % priv->config.rings);
  40. }
  41. static void *safexcel_ring_next_wptr(struct safexcel_crypto_priv *priv,
  42. struct safexcel_ring *ring)
  43. {
  44. void *ptr = ring->write;
  45. if (ring->nr == EIP197_DEFAULT_RING_SIZE - 1)
  46. return ERR_PTR(-ENOMEM);
  47. ring->write += ring->offset;
  48. if (ring->write == ring->base_end)
  49. ring->write = ring->base;
  50. ring->nr++;
  51. return ptr;
  52. }
  53. void *safexcel_ring_next_rptr(struct safexcel_crypto_priv *priv,
  54. struct safexcel_ring *ring)
  55. {
  56. void *ptr = ring->read;
  57. if (!ring->nr)
  58. return ERR_PTR(-ENOENT);
  59. ring->read += ring->offset;
  60. if (ring->read == ring->base_end)
  61. ring->read = ring->base;
  62. ring->nr--;
  63. return ptr;
  64. }
  65. void safexcel_ring_rollback_wptr(struct safexcel_crypto_priv *priv,
  66. struct safexcel_ring *ring)
  67. {
  68. if (!ring->nr)
  69. return;
  70. if (ring->write == ring->base)
  71. ring->write = ring->base_end - ring->offset;
  72. else
  73. ring->write -= ring->offset;
  74. ring->nr--;
  75. }
  76. struct safexcel_command_desc *safexcel_add_cdesc(struct safexcel_crypto_priv *priv,
  77. int ring_id,
  78. bool first, bool last,
  79. dma_addr_t data, u32 data_len,
  80. u32 full_data_len,
  81. dma_addr_t context) {
  82. struct safexcel_command_desc *cdesc;
  83. int i;
  84. cdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].cdr);
  85. if (IS_ERR(cdesc))
  86. return cdesc;
  87. memset(cdesc, 0, sizeof(struct safexcel_command_desc));
  88. cdesc->first_seg = first;
  89. cdesc->last_seg = last;
  90. cdesc->particle_size = data_len;
  91. cdesc->data_lo = lower_32_bits(data);
  92. cdesc->data_hi = upper_32_bits(data);
  93. if (first && context) {
  94. struct safexcel_token *token =
  95. (struct safexcel_token *)cdesc->control_data.token;
  96. cdesc->control_data.packet_length = full_data_len;
  97. cdesc->control_data.options = EIP197_OPTION_MAGIC_VALUE |
  98. EIP197_OPTION_64BIT_CTX |
  99. EIP197_OPTION_CTX_CTRL_IN_CMD;
  100. cdesc->control_data.context_lo =
  101. (lower_32_bits(context) & GENMASK(31, 2)) >> 2;
  102. cdesc->control_data.context_hi = upper_32_bits(context);
  103. /* TODO: large xform HMAC with SHA-384/512 uses refresh = 3 */
  104. cdesc->control_data.refresh = 2;
  105. for (i = 0; i < EIP197_MAX_TOKENS; i++)
  106. eip197_noop_token(&token[i]);
  107. }
  108. return cdesc;
  109. }
  110. struct safexcel_result_desc *safexcel_add_rdesc(struct safexcel_crypto_priv *priv,
  111. int ring_id,
  112. bool first, bool last,
  113. dma_addr_t data, u32 len)
  114. {
  115. struct safexcel_result_desc *rdesc;
  116. rdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].rdr);
  117. if (IS_ERR(rdesc))
  118. return rdesc;
  119. memset(rdesc, 0, sizeof(struct safexcel_result_desc));
  120. rdesc->first_seg = first;
  121. rdesc->last_seg = last;
  122. rdesc->particle_size = len;
  123. rdesc->data_lo = lower_32_bits(data);
  124. rdesc->data_hi = upper_32_bits(data);
  125. return rdesc;
  126. }