virtio_pci_admin_legacy_io.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved
  4. */
  5. #include <linux/virtio_pci_admin.h>
  6. #include "virtio_pci_common.h"
  7. /*
  8. * virtio_pci_admin_has_legacy_io - Checks whether the legacy IO
  9. * commands are supported
  10. * @dev: VF pci_dev
  11. *
  12. * Returns true on success.
  13. */
  14. bool virtio_pci_admin_has_legacy_io(struct pci_dev *pdev)
  15. {
  16. struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
  17. struct virtio_pci_device *vp_dev;
  18. if (!virtio_dev)
  19. return false;
  20. if (!virtio_has_feature(virtio_dev, VIRTIO_F_ADMIN_VQ))
  21. return false;
  22. vp_dev = to_vp_device(virtio_dev);
  23. if ((vp_dev->admin_vq.supported_cmds & VIRTIO_LEGACY_ADMIN_CMD_BITMAP) ==
  24. VIRTIO_LEGACY_ADMIN_CMD_BITMAP)
  25. return true;
  26. return false;
  27. }
  28. EXPORT_SYMBOL_GPL(virtio_pci_admin_has_legacy_io);
  29. static int virtio_pci_admin_legacy_io_write(struct pci_dev *pdev, u16 opcode,
  30. u8 offset, u8 size, u8 *buf)
  31. {
  32. struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
  33. struct virtio_admin_cmd_legacy_wr_data *data;
  34. struct virtio_admin_cmd cmd = {};
  35. struct scatterlist data_sg;
  36. int vf_id;
  37. int ret;
  38. if (!virtio_dev)
  39. return -ENODEV;
  40. vf_id = pci_iov_vf_id(pdev);
  41. if (vf_id < 0)
  42. return vf_id;
  43. data = kzalloc(sizeof(*data) + size, GFP_KERNEL);
  44. if (!data)
  45. return -ENOMEM;
  46. data->offset = offset;
  47. memcpy(data->registers, buf, size);
  48. sg_init_one(&data_sg, data, sizeof(*data) + size);
  49. cmd.opcode = cpu_to_le16(opcode);
  50. cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
  51. cmd.group_member_id = cpu_to_le64(vf_id + 1);
  52. cmd.data_sg = &data_sg;
  53. ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
  54. kfree(data);
  55. return ret;
  56. }
  57. /*
  58. * virtio_pci_admin_legacy_io_write_common - Write legacy common configuration
  59. * of a member device
  60. * @dev: VF pci_dev
  61. * @offset: starting byte offset within the common configuration area to write to
  62. * @size: size of the data to write
  63. * @buf: buffer which holds the data
  64. *
  65. * Note: caller must serialize access for the given device.
  66. * Returns 0 on success, or negative on failure.
  67. */
  68. int virtio_pci_admin_legacy_common_io_write(struct pci_dev *pdev, u8 offset,
  69. u8 size, u8 *buf)
  70. {
  71. return virtio_pci_admin_legacy_io_write(pdev,
  72. VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_WRITE,
  73. offset, size, buf);
  74. }
  75. EXPORT_SYMBOL_GPL(virtio_pci_admin_legacy_common_io_write);
  76. /*
  77. * virtio_pci_admin_legacy_io_write_device - Write legacy device configuration
  78. * of a member device
  79. * @dev: VF pci_dev
  80. * @offset: starting byte offset within the device configuration area to write to
  81. * @size: size of the data to write
  82. * @buf: buffer which holds the data
  83. *
  84. * Note: caller must serialize access for the given device.
  85. * Returns 0 on success, or negative on failure.
  86. */
  87. int virtio_pci_admin_legacy_device_io_write(struct pci_dev *pdev, u8 offset,
  88. u8 size, u8 *buf)
  89. {
  90. return virtio_pci_admin_legacy_io_write(pdev,
  91. VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_WRITE,
  92. offset, size, buf);
  93. }
  94. EXPORT_SYMBOL_GPL(virtio_pci_admin_legacy_device_io_write);
  95. static int virtio_pci_admin_legacy_io_read(struct pci_dev *pdev, u16 opcode,
  96. u8 offset, u8 size, u8 *buf)
  97. {
  98. struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
  99. struct virtio_admin_cmd_legacy_rd_data *data;
  100. struct scatterlist data_sg, result_sg;
  101. struct virtio_admin_cmd cmd = {};
  102. int vf_id;
  103. int ret;
  104. if (!virtio_dev)
  105. return -ENODEV;
  106. vf_id = pci_iov_vf_id(pdev);
  107. if (vf_id < 0)
  108. return vf_id;
  109. data = kzalloc(sizeof(*data), GFP_KERNEL);
  110. if (!data)
  111. return -ENOMEM;
  112. data->offset = offset;
  113. sg_init_one(&data_sg, data, sizeof(*data));
  114. sg_init_one(&result_sg, buf, size);
  115. cmd.opcode = cpu_to_le16(opcode);
  116. cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
  117. cmd.group_member_id = cpu_to_le64(vf_id + 1);
  118. cmd.data_sg = &data_sg;
  119. cmd.result_sg = &result_sg;
  120. ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
  121. kfree(data);
  122. return ret;
  123. }
  124. /*
  125. * virtio_pci_admin_legacy_device_io_read - Read legacy device configuration of
  126. * a member device
  127. * @dev: VF pci_dev
  128. * @offset: starting byte offset within the device configuration area to read from
  129. * @size: size of the data to be read
  130. * @buf: buffer to hold the returned data
  131. *
  132. * Note: caller must serialize access for the given device.
  133. * Returns 0 on success, or negative on failure.
  134. */
  135. int virtio_pci_admin_legacy_device_io_read(struct pci_dev *pdev, u8 offset,
  136. u8 size, u8 *buf)
  137. {
  138. return virtio_pci_admin_legacy_io_read(pdev,
  139. VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ,
  140. offset, size, buf);
  141. }
  142. EXPORT_SYMBOL_GPL(virtio_pci_admin_legacy_device_io_read);
  143. /*
  144. * virtio_pci_admin_legacy_common_io_read - Read legacy common configuration of
  145. * a member device
  146. * @dev: VF pci_dev
  147. * @offset: starting byte offset within the common configuration area to read from
  148. * @size: size of the data to be read
  149. * @buf: buffer to hold the returned data
  150. *
  151. * Note: caller must serialize access for the given device.
  152. * Returns 0 on success, or negative on failure.
  153. */
  154. int virtio_pci_admin_legacy_common_io_read(struct pci_dev *pdev, u8 offset,
  155. u8 size, u8 *buf)
  156. {
  157. return virtio_pci_admin_legacy_io_read(pdev,
  158. VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_READ,
  159. offset, size, buf);
  160. }
  161. EXPORT_SYMBOL_GPL(virtio_pci_admin_legacy_common_io_read);
  162. /*
  163. * virtio_pci_admin_legacy_io_notify_info - Read the queue notification
  164. * information for legacy interface
  165. * @dev: VF pci_dev
  166. * @req_bar_flags: requested bar flags
  167. * @bar: on output the BAR number of the owner or member device
  168. * @bar_offset: on output the offset within bar
  169. *
  170. * Returns 0 on success, or negative on failure.
  171. */
  172. int virtio_pci_admin_legacy_io_notify_info(struct pci_dev *pdev,
  173. u8 req_bar_flags, u8 *bar,
  174. u64 *bar_offset)
  175. {
  176. struct virtio_device *virtio_dev = virtio_pci_vf_get_pf_dev(pdev);
  177. struct virtio_admin_cmd_notify_info_result *result;
  178. struct virtio_admin_cmd cmd = {};
  179. struct scatterlist result_sg;
  180. int vf_id;
  181. int ret;
  182. if (!virtio_dev)
  183. return -ENODEV;
  184. vf_id = pci_iov_vf_id(pdev);
  185. if (vf_id < 0)
  186. return vf_id;
  187. result = kzalloc(sizeof(*result), GFP_KERNEL);
  188. if (!result)
  189. return -ENOMEM;
  190. sg_init_one(&result_sg, result, sizeof(*result));
  191. cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO);
  192. cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
  193. cmd.group_member_id = cpu_to_le64(vf_id + 1);
  194. cmd.result_sg = &result_sg;
  195. ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
  196. if (!ret) {
  197. struct virtio_admin_cmd_notify_info_data *entry;
  198. int i;
  199. ret = -ENOENT;
  200. for (i = 0; i < VIRTIO_ADMIN_CMD_MAX_NOTIFY_INFO; i++) {
  201. entry = &result->entries[i];
  202. if (entry->flags == VIRTIO_ADMIN_CMD_NOTIFY_INFO_FLAGS_END)
  203. break;
  204. if (entry->flags != req_bar_flags)
  205. continue;
  206. *bar = entry->bar;
  207. *bar_offset = le64_to_cpu(entry->offset);
  208. ret = 0;
  209. break;
  210. }
  211. }
  212. kfree(result);
  213. return ret;
  214. }
  215. EXPORT_SYMBOL_GPL(virtio_pci_admin_legacy_io_notify_info);