rebar.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * PCI Resizable BAR Extended Capability handling.
  4. */
  5. #include <linux/bits.h>
  6. #include <linux/bitfield.h>
  7. #include <linux/bitops.h>
  8. #include <linux/errno.h>
  9. #include <linux/export.h>
  10. #include <linux/ioport.h>
  11. #include <linux/log2.h>
  12. #include <linux/pci.h>
  13. #include <linux/sizes.h>
  14. #include <linux/types.h>
  15. #include "pci.h"
  16. #define PCI_REBAR_MIN_SIZE ((resource_size_t)SZ_1M)
  17. /**
  18. * pci_rebar_bytes_to_size - Convert size in bytes to PCI BAR Size
  19. * @bytes: size in bytes
  20. *
  21. * Convert size in bytes to encoded BAR Size in Resizable BAR Capability
  22. * (PCIe r6.2, sec. 7.8.6.3).
  23. *
  24. * Return: encoded BAR Size as defined in the PCIe spec (0=1MB, 31=128TB)
  25. */
  26. int pci_rebar_bytes_to_size(u64 bytes)
  27. {
  28. int rebar_minsize = ilog2(PCI_REBAR_MIN_SIZE);
  29. bytes = roundup_pow_of_two(bytes);
  30. return max(ilog2(bytes), rebar_minsize) - rebar_minsize;
  31. }
  32. EXPORT_SYMBOL_GPL(pci_rebar_bytes_to_size);
  33. /**
  34. * pci_rebar_size_to_bytes - Convert encoded BAR Size to size in bytes
  35. * @size: encoded BAR Size as defined in the PCIe spec (0=1MB, 31=128TB)
  36. *
  37. * Return: BAR size in bytes
  38. */
  39. resource_size_t pci_rebar_size_to_bytes(int size)
  40. {
  41. return 1ULL << (size + ilog2(PCI_REBAR_MIN_SIZE));
  42. }
  43. EXPORT_SYMBOL_GPL(pci_rebar_size_to_bytes);
  44. void pci_rebar_init(struct pci_dev *pdev)
  45. {
  46. pdev->rebar_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR);
  47. }
  48. /**
  49. * pci_rebar_find_pos - find position of resize control reg for BAR
  50. * @pdev: PCI device
  51. * @bar: BAR to find
  52. *
  53. * Helper to find the position of the control register for a BAR.
  54. *
  55. * Return:
  56. * * %-ENOTSUPP if resizable BARs are not supported at all,
  57. * * %-ENOENT if no control register for the BAR could be found.
  58. */
  59. static int pci_rebar_find_pos(struct pci_dev *pdev, int bar)
  60. {
  61. unsigned int pos, nbars, i;
  62. u32 ctrl;
  63. if (pci_resource_is_iov(bar)) {
  64. pos = pci_iov_vf_rebar_cap(pdev);
  65. bar = pci_resource_num_to_vf_bar(bar);
  66. } else {
  67. pos = pdev->rebar_cap;
  68. }
  69. if (!pos)
  70. return -ENOTSUPP;
  71. pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
  72. nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl);
  73. for (i = 0; i < nbars; i++, pos += 8) {
  74. int bar_idx;
  75. pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
  76. bar_idx = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, ctrl);
  77. if (bar_idx == bar)
  78. return pos;
  79. }
  80. return -ENOENT;
  81. }
  82. /**
  83. * pci_rebar_get_possible_sizes - get possible sizes for Resizable BAR
  84. * @pdev: PCI device
  85. * @bar: BAR to query
  86. *
  87. * Get the possible sizes of a resizable BAR as bitmask.
  88. *
  89. * Return: A bitmask of possible sizes (bit 0=1MB, bit 31=128TB), or %0 if
  90. * BAR isn't resizable.
  91. */
  92. u64 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar)
  93. {
  94. int pos;
  95. u32 cap;
  96. pos = pci_rebar_find_pos(pdev, bar);
  97. if (pos < 0)
  98. return 0;
  99. pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap);
  100. cap = FIELD_GET(PCI_REBAR_CAP_SIZES, cap);
  101. /* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */
  102. if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f &&
  103. bar == 0 && cap == 0x700)
  104. return 0x3f00;
  105. return cap;
  106. }
  107. EXPORT_SYMBOL(pci_rebar_get_possible_sizes);
  108. /**
  109. * pci_rebar_size_supported - check if size is supported for BAR
  110. * @pdev: PCI device
  111. * @bar: BAR to check
  112. * @size: encoded size as defined in the PCIe spec (0=1MB, 31=128TB)
  113. *
  114. * Return: %true if @bar is resizable and @size is supported, otherwise
  115. * %false.
  116. */
  117. bool pci_rebar_size_supported(struct pci_dev *pdev, int bar, int size)
  118. {
  119. u64 sizes = pci_rebar_get_possible_sizes(pdev, bar);
  120. if (size < 0 || size > ilog2(SZ_128T) - ilog2(PCI_REBAR_MIN_SIZE))
  121. return false;
  122. return BIT(size) & sizes;
  123. }
  124. EXPORT_SYMBOL_GPL(pci_rebar_size_supported);
  125. /**
  126. * pci_rebar_get_max_size - get the maximum supported size of a BAR
  127. * @pdev: PCI device
  128. * @bar: BAR to query
  129. *
  130. * Get the largest supported size of a resizable BAR as a size.
  131. *
  132. * Return: the encoded maximum BAR size as defined in the PCIe spec
  133. * (0=1MB, 31=128TB), or %-NOENT on error.
  134. */
  135. int pci_rebar_get_max_size(struct pci_dev *pdev, int bar)
  136. {
  137. u64 sizes;
  138. sizes = pci_rebar_get_possible_sizes(pdev, bar);
  139. if (!sizes)
  140. return -ENOENT;
  141. return __fls(sizes);
  142. }
  143. EXPORT_SYMBOL_GPL(pci_rebar_get_max_size);
  144. /**
  145. * pci_rebar_get_current_size - get the current size of a Resizable BAR
  146. * @pdev: PCI device
  147. * @bar: BAR to get the size from
  148. *
  149. * Read the current size of a BAR from the Resizable BAR config.
  150. *
  151. * Return: BAR Size if @bar is resizable (0=1MB, 31=128TB), or negative on
  152. * error.
  153. */
  154. int pci_rebar_get_current_size(struct pci_dev *pdev, int bar)
  155. {
  156. int pos;
  157. u32 ctrl;
  158. pos = pci_rebar_find_pos(pdev, bar);
  159. if (pos < 0)
  160. return pos;
  161. pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
  162. return FIELD_GET(PCI_REBAR_CTRL_BAR_SIZE, ctrl);
  163. }
  164. /**
  165. * pci_rebar_set_size - set a new size for a Resizable BAR
  166. * @pdev: PCI device
  167. * @bar: BAR to set size to
  168. * @size: new size as defined in the PCIe spec (0=1MB, 31=128TB)
  169. *
  170. * Set the new size of a BAR as defined in the spec.
  171. *
  172. * Return: %0 if resizing was successful, or negative on error.
  173. */
  174. int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size)
  175. {
  176. int pos;
  177. u32 ctrl;
  178. pos = pci_rebar_find_pos(pdev, bar);
  179. if (pos < 0)
  180. return pos;
  181. pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
  182. ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
  183. ctrl |= FIELD_PREP(PCI_REBAR_CTRL_BAR_SIZE, size);
  184. pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl);
  185. if (pci_resource_is_iov(bar))
  186. pci_iov_resource_set_size(pdev, bar, size);
  187. return 0;
  188. }
  189. void pci_restore_rebar_state(struct pci_dev *pdev)
  190. {
  191. unsigned int pos, nbars, i;
  192. u32 ctrl;
  193. pos = pdev->rebar_cap;
  194. if (!pos)
  195. return;
  196. pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
  197. nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl);
  198. for (i = 0; i < nbars; i++, pos += 8) {
  199. struct resource *res;
  200. int bar_idx, size;
  201. pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
  202. bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX;
  203. res = pci_resource_n(pdev, bar_idx);
  204. size = pci_rebar_bytes_to_size(resource_size(res));
  205. ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
  206. ctrl |= FIELD_PREP(PCI_REBAR_CTRL_BAR_SIZE, size);
  207. pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl);
  208. }
  209. }
  210. static bool pci_resize_is_memory_decoding_enabled(struct pci_dev *dev,
  211. int resno)
  212. {
  213. u16 cmd;
  214. if (pci_resource_is_iov(resno))
  215. return pci_iov_is_memory_decoding_enabled(dev);
  216. pci_read_config_word(dev, PCI_COMMAND, &cmd);
  217. return cmd & PCI_COMMAND_MEMORY;
  218. }
  219. void pci_resize_resource_set_size(struct pci_dev *dev, int resno, int size)
  220. {
  221. resource_size_t res_size = pci_rebar_size_to_bytes(size);
  222. struct resource *res = pci_resource_n(dev, resno);
  223. if (pci_resource_is_iov(resno))
  224. res_size *= pci_sriov_get_totalvfs(dev);
  225. resource_set_size(res, res_size);
  226. }
  227. /**
  228. * pci_resize_resource - reconfigure a Resizable BAR and resources
  229. * @dev: the PCI device
  230. * @resno: index of the BAR to be resized
  231. * @size: new size as defined in the spec (0=1MB, 31=128TB)
  232. * @exclude_bars: a mask of BARs that should not be released
  233. *
  234. * Reconfigure @resno to @size and re-run resource assignment algorithm
  235. * with the new size.
  236. *
  237. * Prior to resize, release @dev resources that share a bridge window with
  238. * @resno. This unpins the bridge window resource to allow changing it.
  239. *
  240. * The caller may prevent releasing a particular BAR by providing
  241. * @exclude_bars mask, but this may result in the resize operation failing
  242. * due to insufficient space.
  243. *
  244. * Return: 0 on success, or negative on error. In case of an error, the
  245. * resources are restored to their original places.
  246. */
  247. int pci_resize_resource(struct pci_dev *dev, int resno, int size,
  248. int exclude_bars)
  249. {
  250. struct pci_host_bridge *host;
  251. /* Check if we must preserve the firmware's resource assignment */
  252. host = pci_find_host_bridge(dev->bus);
  253. if (host->preserve_config)
  254. return -ENOTSUPP;
  255. if (pci_resize_is_memory_decoding_enabled(dev, resno))
  256. return -EBUSY;
  257. if (!pci_rebar_size_supported(dev, resno, size))
  258. return -EINVAL;
  259. return pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
  260. }
  261. EXPORT_SYMBOL(pci_resize_resource);