scif_ports.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Intel MIC Platform Software Stack (MPSS)
  3. *
  4. * Copyright(c) 2014 Intel Corporation.
  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, version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * Intel SCIF driver.
  16. *
  17. */
  18. #include <linux/idr.h>
  19. #include "scif_main.h"
  20. #define SCIF_PORT_COUNT 0x10000 /* Ports available */
  21. struct idr scif_ports;
  22. /*
  23. * struct scif_port - SCIF port information
  24. *
  25. * @ref_cnt - Reference count since there can be multiple endpoints
  26. * created via scif_accept(..) simultaneously using a port.
  27. */
  28. struct scif_port {
  29. int ref_cnt;
  30. };
  31. /**
  32. * __scif_get_port - Reserve a specified port # for SCIF and add it
  33. * to the global list.
  34. * @port : port # to be reserved.
  35. *
  36. * @return : Allocated SCIF port #, or -ENOSPC if port unavailable.
  37. * On memory allocation failure, returns -ENOMEM.
  38. */
  39. static int __scif_get_port(int start, int end)
  40. {
  41. int id;
  42. struct scif_port *port = kzalloc(sizeof(*port), GFP_ATOMIC);
  43. if (!port)
  44. return -ENOMEM;
  45. spin_lock(&scif_info.port_lock);
  46. id = idr_alloc(&scif_ports, port, start, end, GFP_ATOMIC);
  47. if (id >= 0)
  48. port->ref_cnt++;
  49. spin_unlock(&scif_info.port_lock);
  50. return id;
  51. }
  52. /**
  53. * scif_rsrv_port - Reserve a specified port # for SCIF.
  54. * @port : port # to be reserved.
  55. *
  56. * @return : Allocated SCIF port #, or -ENOSPC if port unavailable.
  57. * On memory allocation failure, returns -ENOMEM.
  58. */
  59. int scif_rsrv_port(u16 port)
  60. {
  61. return __scif_get_port(port, port + 1);
  62. }
  63. /**
  64. * scif_get_new_port - Get and reserve any port # for SCIF in the range
  65. * SCIF_PORT_RSVD + 1 to SCIF_PORT_COUNT - 1.
  66. *
  67. * @return : Allocated SCIF port #, or -ENOSPC if no ports available.
  68. * On memory allocation failure, returns -ENOMEM.
  69. */
  70. int scif_get_new_port(void)
  71. {
  72. return __scif_get_port(SCIF_PORT_RSVD + 1, SCIF_PORT_COUNT);
  73. }
  74. /**
  75. * scif_get_port - Increment the reference count for a SCIF port
  76. * @id : SCIF port
  77. *
  78. * @return : None
  79. */
  80. void scif_get_port(u16 id)
  81. {
  82. struct scif_port *port;
  83. if (!id)
  84. return;
  85. spin_lock(&scif_info.port_lock);
  86. port = idr_find(&scif_ports, id);
  87. if (port)
  88. port->ref_cnt++;
  89. spin_unlock(&scif_info.port_lock);
  90. }
  91. /**
  92. * scif_put_port - Release a reserved SCIF port
  93. * @id : SCIF port to be released.
  94. *
  95. * @return : None
  96. */
  97. void scif_put_port(u16 id)
  98. {
  99. struct scif_port *port;
  100. if (!id)
  101. return;
  102. spin_lock(&scif_info.port_lock);
  103. port = idr_find(&scif_ports, id);
  104. if (port) {
  105. port->ref_cnt--;
  106. if (!port->ref_cnt) {
  107. idr_remove(&scif_ports, id);
  108. kfree(port);
  109. }
  110. }
  111. spin_unlock(&scif_info.port_lock);
  112. }