mic_smpt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*
  2. * Intel MIC Platform Software Stack (MPSS)
  3. *
  4. * Copyright(c) 2013 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. * The full GNU General Public License is included in this distribution in
  16. * the file called "COPYING".
  17. *
  18. * Intel MIC Host driver.
  19. *
  20. */
  21. #include <linux/pci.h>
  22. #include "../common/mic_dev.h"
  23. #include "mic_device.h"
  24. #include "mic_smpt.h"
  25. static inline u64 mic_system_page_mask(struct mic_device *mdev)
  26. {
  27. return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
  28. }
  29. static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
  30. {
  31. return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
  32. }
  33. static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
  34. {
  35. return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
  36. }
  37. static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
  38. {
  39. return pa & mic_system_page_mask(mdev);
  40. }
  41. static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
  42. {
  43. return ALIGN(pa - mic_system_page_mask(mdev),
  44. mdev->smpt->info.page_size);
  45. }
  46. static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
  47. {
  48. return ALIGN(pa, mdev->smpt->info.page_size);
  49. }
  50. /* Total Cumulative system memory accessible by MIC across all SMPT entries */
  51. static inline u64 mic_max_system_memory(struct mic_device *mdev)
  52. {
  53. return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
  54. }
  55. /* Maximum system memory address accessible by MIC */
  56. static inline u64 mic_max_system_addr(struct mic_device *mdev)
  57. {
  58. return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
  59. }
  60. /* Check if the DMA address is a MIC system memory address */
  61. static inline bool
  62. mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
  63. {
  64. return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
  65. }
  66. /* Populate an SMPT entry and update the reference counts. */
  67. static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
  68. int entries, struct mic_device *mdev)
  69. {
  70. struct mic_smpt_info *smpt_info = mdev->smpt;
  71. int i;
  72. for (i = spt; i < spt + entries; i++,
  73. addr += smpt_info->info.page_size) {
  74. if (!smpt_info->entry[i].ref_count &&
  75. (smpt_info->entry[i].dma_addr != addr)) {
  76. mdev->smpt_ops->set(mdev, addr, i);
  77. smpt_info->entry[i].dma_addr = addr;
  78. }
  79. smpt_info->entry[i].ref_count += ref[i - spt];
  80. }
  81. }
  82. /*
  83. * Find an available MIC address in MIC SMPT address space
  84. * for a given DMA address and size.
  85. */
  86. static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
  87. int entries, s64 *ref, size_t size)
  88. {
  89. int spt;
  90. int ae = 0;
  91. int i;
  92. unsigned long flags;
  93. dma_addr_t mic_addr = 0;
  94. dma_addr_t addr = dma_addr;
  95. struct mic_smpt_info *smpt_info = mdev->smpt;
  96. spin_lock_irqsave(&smpt_info->smpt_lock, flags);
  97. /* find existing entries */
  98. for (i = 0; i < smpt_info->info.num_reg; i++) {
  99. if (smpt_info->entry[i].dma_addr == addr) {
  100. ae++;
  101. addr += smpt_info->info.page_size;
  102. } else if (ae) /* cannot find contiguous entries */
  103. goto not_found;
  104. if (ae == entries)
  105. goto found;
  106. }
  107. /* find free entry */
  108. for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
  109. ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
  110. if (ae == entries)
  111. goto found;
  112. }
  113. not_found:
  114. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  115. return mic_addr;
  116. found:
  117. spt = i - entries + 1;
  118. mic_addr = mic_smpt_to_pa(mdev, spt);
  119. mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
  120. smpt_info->map_count++;
  121. smpt_info->ref_count += (s64)size;
  122. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  123. return mic_addr;
  124. }
  125. /*
  126. * Returns number of smpt entries needed for dma_addr to dma_addr + size
  127. * also returns the reference count array for each of those entries
  128. * and the starting smpt address
  129. */
  130. static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
  131. size_t size, s64 *ref, u64 *smpt_start)
  132. {
  133. u64 start = dma_addr;
  134. u64 end = dma_addr + size;
  135. int i = 0;
  136. while (start < end) {
  137. ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
  138. end) - start;
  139. start = mic_smpt_align_high(mdev, start + 1);
  140. }
  141. if (smpt_start)
  142. *smpt_start = mic_smpt_align_low(mdev, dma_addr);
  143. return i;
  144. }
  145. /*
  146. * mic_to_dma_addr - Converts a MIC address to a DMA address.
  147. *
  148. * @mdev: pointer to mic_device instance.
  149. * @mic_addr: MIC address.
  150. *
  151. * returns a DMA address.
  152. */
  153. dma_addr_t mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
  154. {
  155. struct mic_smpt_info *smpt_info = mdev->smpt;
  156. int spt;
  157. dma_addr_t dma_addr;
  158. if (!mic_is_system_addr(mdev, mic_addr)) {
  159. dev_err(&mdev->pdev->dev,
  160. "mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
  161. return -EINVAL;
  162. }
  163. spt = mic_sys_addr_to_smpt(mdev, mic_addr);
  164. dma_addr = smpt_info->entry[spt].dma_addr +
  165. mic_smpt_offset(mdev, mic_addr);
  166. return dma_addr;
  167. }
  168. /**
  169. * mic_map - Maps a DMA address to a MIC physical address.
  170. *
  171. * @mdev: pointer to mic_device instance.
  172. * @dma_addr: DMA address.
  173. * @size: Size of the region to be mapped.
  174. *
  175. * This API converts the DMA address provided to a DMA address understood
  176. * by MIC. Caller should check for errors by calling mic_map_error(..).
  177. *
  178. * returns DMA address as required by MIC.
  179. */
  180. dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
  181. {
  182. dma_addr_t mic_addr = 0;
  183. int num_entries;
  184. s64 *ref;
  185. u64 smpt_start;
  186. if (!size || size > mic_max_system_memory(mdev))
  187. return mic_addr;
  188. ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64), GFP_ATOMIC);
  189. if (!ref)
  190. return mic_addr;
  191. num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
  192. ref, &smpt_start);
  193. /* Set the smpt table appropriately and get 16G aligned mic address */
  194. mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
  195. kfree(ref);
  196. /*
  197. * If mic_addr is zero then its an error case
  198. * since mic_addr can never be zero.
  199. * else generate mic_addr by adding the 16G offset in dma_addr
  200. */
  201. if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
  202. dev_err(&mdev->pdev->dev,
  203. "mic_map failed dma_addr 0x%llx size 0x%lx\n",
  204. dma_addr, size);
  205. return mic_addr;
  206. } else {
  207. return mic_addr + mic_smpt_offset(mdev, dma_addr);
  208. }
  209. }
  210. /**
  211. * mic_unmap - Unmaps a MIC physical address.
  212. *
  213. * @mdev: pointer to mic_device instance.
  214. * @mic_addr: MIC physical address.
  215. * @size: Size of the region to be unmapped.
  216. *
  217. * This API unmaps the mappings created by mic_map(..).
  218. *
  219. * returns None.
  220. */
  221. void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
  222. {
  223. struct mic_smpt_info *smpt_info = mdev->smpt;
  224. s64 *ref;
  225. int num_smpt;
  226. int spt;
  227. int i;
  228. unsigned long flags;
  229. if (!size)
  230. return;
  231. if (!mic_is_system_addr(mdev, mic_addr)) {
  232. dev_err(&mdev->pdev->dev,
  233. "invalid address: 0x%llx\n", mic_addr);
  234. return;
  235. }
  236. spt = mic_sys_addr_to_smpt(mdev, mic_addr);
  237. ref = kmalloc_array(mdev->smpt->info.num_reg, sizeof(s64), GFP_ATOMIC);
  238. if (!ref)
  239. return;
  240. /* Get number of smpt entries to be mapped, ref count array */
  241. num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
  242. spin_lock_irqsave(&smpt_info->smpt_lock, flags);
  243. smpt_info->unmap_count++;
  244. smpt_info->ref_count -= (s64)size;
  245. for (i = spt; i < spt + num_smpt; i++) {
  246. smpt_info->entry[i].ref_count -= ref[i - spt];
  247. if (smpt_info->entry[i].ref_count < 0)
  248. dev_warn(&mdev->pdev->dev,
  249. "ref count for entry %d is negative\n", i);
  250. }
  251. spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
  252. kfree(ref);
  253. }
  254. /**
  255. * mic_map_single - Maps a virtual address to a MIC physical address.
  256. *
  257. * @mdev: pointer to mic_device instance.
  258. * @va: Kernel direct mapped virtual address.
  259. * @size: Size of the region to be mapped.
  260. *
  261. * This API calls pci_map_single(..) for the direct mapped virtual address
  262. * and then converts the DMA address provided to a DMA address understood
  263. * by MIC. Caller should check for errors by calling mic_map_error(..).
  264. *
  265. * returns DMA address as required by MIC.
  266. */
  267. dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
  268. {
  269. dma_addr_t mic_addr = 0;
  270. struct pci_dev *pdev = mdev->pdev;
  271. dma_addr_t dma_addr =
  272. pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
  273. if (!pci_dma_mapping_error(pdev, dma_addr)) {
  274. mic_addr = mic_map(mdev, dma_addr, size);
  275. if (!mic_addr) {
  276. dev_err(&mdev->pdev->dev,
  277. "mic_map failed dma_addr 0x%llx size 0x%lx\n",
  278. dma_addr, size);
  279. pci_unmap_single(pdev, dma_addr,
  280. size, PCI_DMA_BIDIRECTIONAL);
  281. }
  282. }
  283. return mic_addr;
  284. }
  285. /**
  286. * mic_unmap_single - Unmaps a MIC physical address.
  287. *
  288. * @mdev: pointer to mic_device instance.
  289. * @mic_addr: MIC physical address.
  290. * @size: Size of the region to be unmapped.
  291. *
  292. * This API unmaps the mappings created by mic_map_single(..).
  293. *
  294. * returns None.
  295. */
  296. void
  297. mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
  298. {
  299. struct pci_dev *pdev = mdev->pdev;
  300. dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
  301. mic_unmap(mdev, mic_addr, size);
  302. pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
  303. }
  304. /**
  305. * mic_smpt_init - Initialize MIC System Memory Page Tables.
  306. *
  307. * @mdev: pointer to mic_device instance.
  308. *
  309. * returns 0 for success and -errno for error.
  310. */
  311. int mic_smpt_init(struct mic_device *mdev)
  312. {
  313. int i, err = 0;
  314. dma_addr_t dma_addr;
  315. struct mic_smpt_info *smpt_info;
  316. mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
  317. if (!mdev->smpt)
  318. return -ENOMEM;
  319. smpt_info = mdev->smpt;
  320. mdev->smpt_ops->init(mdev);
  321. smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
  322. sizeof(*smpt_info->entry), GFP_KERNEL);
  323. if (!smpt_info->entry) {
  324. err = -ENOMEM;
  325. goto free_smpt;
  326. }
  327. spin_lock_init(&smpt_info->smpt_lock);
  328. for (i = 0; i < smpt_info->info.num_reg; i++) {
  329. dma_addr = i * smpt_info->info.page_size;
  330. smpt_info->entry[i].dma_addr = dma_addr;
  331. smpt_info->entry[i].ref_count = 0;
  332. mdev->smpt_ops->set(mdev, dma_addr, i);
  333. }
  334. smpt_info->ref_count = 0;
  335. smpt_info->map_count = 0;
  336. smpt_info->unmap_count = 0;
  337. return 0;
  338. free_smpt:
  339. kfree(smpt_info);
  340. return err;
  341. }
  342. /**
  343. * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
  344. *
  345. * @mdev: pointer to mic_device instance.
  346. *
  347. * returns None.
  348. */
  349. void mic_smpt_uninit(struct mic_device *mdev)
  350. {
  351. struct mic_smpt_info *smpt_info = mdev->smpt;
  352. int i;
  353. dev_dbg(&mdev->pdev->dev,
  354. "nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
  355. mdev->id, smpt_info->ref_count,
  356. smpt_info->map_count, smpt_info->unmap_count);
  357. for (i = 0; i < smpt_info->info.num_reg; i++) {
  358. dev_dbg(&mdev->pdev->dev,
  359. "SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
  360. i, smpt_info->entry[i].dma_addr,
  361. smpt_info->entry[i].ref_count);
  362. if (smpt_info->entry[i].ref_count)
  363. dev_warn(&mdev->pdev->dev,
  364. "ref count for entry %d is not zero\n", i);
  365. }
  366. kfree(smpt_info->entry);
  367. kfree(smpt_info);
  368. }
  369. /**
  370. * mic_smpt_restore - Restore MIC System Memory Page Tables.
  371. *
  372. * @mdev: pointer to mic_device instance.
  373. *
  374. * Restore the SMPT registers to values previously stored in the
  375. * SW data structures. Some MIC steppings lose register state
  376. * across resets and this API should be called for performing
  377. * a restore operation if required.
  378. *
  379. * returns None.
  380. */
  381. void mic_smpt_restore(struct mic_device *mdev)
  382. {
  383. int i;
  384. dma_addr_t dma_addr;
  385. for (i = 0; i < mdev->smpt->info.num_reg; i++) {
  386. dma_addr = mdev->smpt->entry[i].dma_addr;
  387. mdev->smpt_ops->set(mdev, dma_addr, i);
  388. }
  389. }