spu_manage.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * spu management operations for of based platforms
  4. *
  5. * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
  6. * Copyright 2006 Sony Corp.
  7. * (C) Copyright 2007 TOSHIBA CORPORATION
  8. */
  9. #include <linux/interrupt.h>
  10. #include <linux/list.h>
  11. #include <linux/export.h>
  12. #include <linux/ptrace.h>
  13. #include <linux/wait.h>
  14. #include <linux/mm.h>
  15. #include <linux/io.h>
  16. #include <linux/mutex.h>
  17. #include <linux/device.h>
  18. #include <linux/of_address.h>
  19. #include <linux/of_irq.h>
  20. #include <asm/spu.h>
  21. #include <asm/spu_priv1.h>
  22. #include <asm/firmware.h>
  23. #include "spufs/spufs.h"
  24. #include "interrupt.h"
  25. #include "spu_priv1_mmio.h"
  26. struct device_node *spu_devnode(struct spu *spu)
  27. {
  28. return spu->devnode;
  29. }
  30. EXPORT_SYMBOL_GPL(spu_devnode);
  31. static u64 __init find_spu_unit_number(struct device_node *spe)
  32. {
  33. const unsigned int *prop;
  34. int proplen;
  35. /* new device trees should provide the physical-id attribute */
  36. prop = of_get_property(spe, "physical-id", &proplen);
  37. if (proplen == 4)
  38. return (u64)*prop;
  39. /* celleb device tree provides the unit-id */
  40. prop = of_get_property(spe, "unit-id", &proplen);
  41. if (proplen == 4)
  42. return (u64)*prop;
  43. /* legacy device trees provide the id in the reg attribute */
  44. prop = of_get_property(spe, "reg", &proplen);
  45. if (proplen == 4)
  46. return (u64)*prop;
  47. return 0;
  48. }
  49. static void spu_unmap(struct spu *spu)
  50. {
  51. if (!firmware_has_feature(FW_FEATURE_LPAR))
  52. iounmap(spu->priv1);
  53. iounmap(spu->priv2);
  54. iounmap(spu->problem);
  55. iounmap((__force u8 __iomem *)spu->local_store);
  56. }
  57. static int __init spu_map_interrupts_old(struct spu *spu,
  58. struct device_node *np)
  59. {
  60. unsigned int isrc;
  61. const u32 *tmp;
  62. int nid;
  63. /* Get the interrupt source unit from the device-tree */
  64. tmp = of_get_property(np, "isrc", NULL);
  65. if (!tmp)
  66. return -ENODEV;
  67. isrc = tmp[0];
  68. tmp = of_get_property(np->parent->parent, "node-id", NULL);
  69. if (!tmp) {
  70. printk(KERN_WARNING "%s: can't find node-id\n", __func__);
  71. nid = spu->node;
  72. } else
  73. nid = tmp[0];
  74. /* Add the node number */
  75. isrc |= nid << IIC_IRQ_NODE_SHIFT;
  76. /* Now map interrupts of all 3 classes */
  77. spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
  78. spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
  79. spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
  80. /* Right now, we only fail if class 2 failed */
  81. if (!spu->irqs[2])
  82. return -EINVAL;
  83. return 0;
  84. }
  85. static void __iomem * __init spu_map_prop_old(struct spu *spu,
  86. struct device_node *n,
  87. const char *name)
  88. {
  89. const struct address_prop {
  90. unsigned long address;
  91. unsigned int len;
  92. } __attribute__((packed)) *prop;
  93. int proplen;
  94. prop = of_get_property(n, name, &proplen);
  95. if (prop == NULL || proplen != sizeof (struct address_prop))
  96. return NULL;
  97. return ioremap(prop->address, prop->len);
  98. }
  99. static int __init spu_map_device_old(struct spu *spu)
  100. {
  101. struct device_node *node = spu->devnode;
  102. const char *prop;
  103. int ret;
  104. ret = -ENODEV;
  105. spu->name = of_get_property(node, "name", NULL);
  106. if (!spu->name)
  107. goto out;
  108. prop = of_get_property(node, "local-store", NULL);
  109. if (!prop)
  110. goto out;
  111. spu->local_store_phys = *(unsigned long *)prop;
  112. /* we use local store as ram, not io memory */
  113. spu->local_store = (void __force *)
  114. spu_map_prop_old(spu, node, "local-store");
  115. if (!spu->local_store)
  116. goto out;
  117. prop = of_get_property(node, "problem", NULL);
  118. if (!prop)
  119. goto out_unmap;
  120. spu->problem_phys = *(unsigned long *)prop;
  121. spu->problem = spu_map_prop_old(spu, node, "problem");
  122. if (!spu->problem)
  123. goto out_unmap;
  124. spu->priv2 = spu_map_prop_old(spu, node, "priv2");
  125. if (!spu->priv2)
  126. goto out_unmap;
  127. if (!firmware_has_feature(FW_FEATURE_LPAR)) {
  128. spu->priv1 = spu_map_prop_old(spu, node, "priv1");
  129. if (!spu->priv1)
  130. goto out_unmap;
  131. }
  132. ret = 0;
  133. goto out;
  134. out_unmap:
  135. spu_unmap(spu);
  136. out:
  137. return ret;
  138. }
  139. static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
  140. {
  141. int i;
  142. for (i=0; i < 3; i++) {
  143. spu->irqs[i] = irq_of_parse_and_map(np, i);
  144. if (!spu->irqs[i])
  145. goto err;
  146. }
  147. return 0;
  148. err:
  149. pr_debug("failed to map irq %x for spu %s\n", i, spu->name);
  150. for (; i >= 0; i--) {
  151. if (spu->irqs[i])
  152. irq_dispose_mapping(spu->irqs[i]);
  153. }
  154. return -EINVAL;
  155. }
  156. static int __init spu_map_resource(struct spu *spu, int nr,
  157. void __iomem** virt, unsigned long *phys)
  158. {
  159. struct device_node *np = spu->devnode;
  160. struct resource resource = { };
  161. unsigned long len;
  162. int ret;
  163. ret = of_address_to_resource(np, nr, &resource);
  164. if (ret)
  165. return ret;
  166. if (phys)
  167. *phys = resource.start;
  168. len = resource_size(&resource);
  169. *virt = ioremap(resource.start, len);
  170. if (!*virt)
  171. return -EINVAL;
  172. return 0;
  173. }
  174. static int __init spu_map_device(struct spu *spu)
  175. {
  176. struct device_node *np = spu->devnode;
  177. int ret = -ENODEV;
  178. spu->name = of_get_property(np, "name", NULL);
  179. if (!spu->name)
  180. goto out;
  181. ret = spu_map_resource(spu, 0, (void __iomem**)&spu->local_store,
  182. &spu->local_store_phys);
  183. if (ret) {
  184. pr_debug("spu_new: failed to map %pOF resource 0\n",
  185. np);
  186. goto out;
  187. }
  188. ret = spu_map_resource(spu, 1, (void __iomem**)&spu->problem,
  189. &spu->problem_phys);
  190. if (ret) {
  191. pr_debug("spu_new: failed to map %pOF resource 1\n",
  192. np);
  193. goto out_unmap;
  194. }
  195. ret = spu_map_resource(spu, 2, (void __iomem**)&spu->priv2, NULL);
  196. if (ret) {
  197. pr_debug("spu_new: failed to map %pOF resource 2\n",
  198. np);
  199. goto out_unmap;
  200. }
  201. if (!firmware_has_feature(FW_FEATURE_LPAR))
  202. ret = spu_map_resource(spu, 3,
  203. (void __iomem**)&spu->priv1, NULL);
  204. if (ret) {
  205. pr_debug("spu_new: failed to map %pOF resource 3\n",
  206. np);
  207. goto out_unmap;
  208. }
  209. pr_debug("spu_new: %pOF maps:\n", np);
  210. pr_debug(" local store : 0x%016lx -> 0x%p\n",
  211. spu->local_store_phys, spu->local_store);
  212. pr_debug(" problem state : 0x%016lx -> 0x%p\n",
  213. spu->problem_phys, spu->problem);
  214. pr_debug(" priv2 : 0x%p\n", spu->priv2);
  215. pr_debug(" priv1 : 0x%p\n", spu->priv1);
  216. return 0;
  217. out_unmap:
  218. spu_unmap(spu);
  219. out:
  220. pr_debug("failed to map spe %s: %d\n", spu->name, ret);
  221. return ret;
  222. }
  223. static int __init of_enumerate_spus(int (*fn)(void *data))
  224. {
  225. int ret;
  226. struct device_node *node;
  227. unsigned int n = 0;
  228. ret = -ENODEV;
  229. for_each_node_by_type(node, "spe") {
  230. ret = fn(node);
  231. if (ret) {
  232. printk(KERN_WARNING "%s: Error initializing %pOFn\n",
  233. __func__, node);
  234. of_node_put(node);
  235. break;
  236. }
  237. n++;
  238. }
  239. return ret ? ret : n;
  240. }
  241. static int __init of_create_spu(struct spu *spu, void *data)
  242. {
  243. int ret;
  244. struct device_node *spe = (struct device_node *)data;
  245. static int legacy_map = 0, legacy_irq = 0;
  246. spu->devnode = of_node_get(spe);
  247. spu->spe_id = find_spu_unit_number(spe);
  248. spu->node = of_node_to_nid(spe);
  249. if (spu->node >= MAX_NUMNODES) {
  250. printk(KERN_WARNING "SPE %pOF on node %d ignored,"
  251. " node number too big\n", spe, spu->node);
  252. printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n");
  253. ret = -ENODEV;
  254. goto out;
  255. }
  256. ret = spu_map_device(spu);
  257. if (ret) {
  258. if (!legacy_map) {
  259. legacy_map = 1;
  260. printk(KERN_WARNING "%s: Legacy device tree found, "
  261. "trying to map old style\n", __func__);
  262. }
  263. ret = spu_map_device_old(spu);
  264. if (ret) {
  265. printk(KERN_ERR "Unable to map %s\n",
  266. spu->name);
  267. goto out;
  268. }
  269. }
  270. ret = spu_map_interrupts(spu, spe);
  271. if (ret) {
  272. if (!legacy_irq) {
  273. legacy_irq = 1;
  274. printk(KERN_WARNING "%s: Legacy device tree found, "
  275. "trying old style irq\n", __func__);
  276. }
  277. ret = spu_map_interrupts_old(spu, spe);
  278. if (ret) {
  279. printk(KERN_ERR "%s: could not map interrupts\n",
  280. spu->name);
  281. goto out_unmap;
  282. }
  283. }
  284. pr_debug("Using SPE %s %p %p %p %p %d\n", spu->name,
  285. spu->local_store, spu->problem, spu->priv1,
  286. spu->priv2, spu->number);
  287. goto out;
  288. out_unmap:
  289. spu_unmap(spu);
  290. out:
  291. return ret;
  292. }
  293. static int of_destroy_spu(struct spu *spu)
  294. {
  295. spu_unmap(spu);
  296. of_node_put(spu->devnode);
  297. return 0;
  298. }
  299. static void enable_spu_by_master_run(struct spu_context *ctx)
  300. {
  301. ctx->ops->master_start(ctx);
  302. }
  303. static void disable_spu_by_master_run(struct spu_context *ctx)
  304. {
  305. ctx->ops->master_stop(ctx);
  306. }
  307. /* Hardcoded affinity idxs for qs20 */
  308. #define QS20_SPES_PER_BE 8
  309. static int qs20_reg_idxs[QS20_SPES_PER_BE] = { 0, 2, 4, 6, 7, 5, 3, 1 };
  310. static int qs20_reg_memory[QS20_SPES_PER_BE] = { 1, 1, 0, 0, 0, 0, 0, 0 };
  311. static struct spu *__init spu_lookup_reg(int node, u32 reg)
  312. {
  313. struct spu *spu;
  314. const u32 *spu_reg;
  315. list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
  316. spu_reg = of_get_property(spu_devnode(spu), "reg", NULL);
  317. if (*spu_reg == reg)
  318. return spu;
  319. }
  320. return NULL;
  321. }
  322. static void __init init_affinity_qs20_harcoded(void)
  323. {
  324. int node, i;
  325. struct spu *last_spu, *spu;
  326. u32 reg;
  327. for (node = 0; node < MAX_NUMNODES; node++) {
  328. last_spu = NULL;
  329. for (i = 0; i < QS20_SPES_PER_BE; i++) {
  330. reg = qs20_reg_idxs[i];
  331. spu = spu_lookup_reg(node, reg);
  332. if (!spu)
  333. continue;
  334. spu->has_mem_affinity = qs20_reg_memory[reg];
  335. if (last_spu)
  336. list_add_tail(&spu->aff_list,
  337. &last_spu->aff_list);
  338. last_spu = spu;
  339. }
  340. }
  341. }
  342. static int __init of_has_vicinity(void)
  343. {
  344. struct device_node *dn;
  345. for_each_node_by_type(dn, "spe") {
  346. if (of_property_present(dn, "vicinity")) {
  347. of_node_put(dn);
  348. return 1;
  349. }
  350. }
  351. return 0;
  352. }
  353. static struct spu *__init devnode_spu(int cbe, struct device_node *dn)
  354. {
  355. struct spu *spu;
  356. list_for_each_entry(spu, &cbe_spu_info[cbe].spus, cbe_list)
  357. if (spu_devnode(spu) == dn)
  358. return spu;
  359. return NULL;
  360. }
  361. static struct spu * __init
  362. neighbour_spu(int cbe, struct device_node *target, struct device_node *avoid)
  363. {
  364. struct spu *spu;
  365. struct device_node *spu_dn;
  366. const phandle *vic_handles;
  367. int lenp, i;
  368. list_for_each_entry(spu, &cbe_spu_info[cbe].spus, cbe_list) {
  369. spu_dn = spu_devnode(spu);
  370. if (spu_dn == avoid)
  371. continue;
  372. vic_handles = of_get_property(spu_dn, "vicinity", &lenp);
  373. for (i=0; i < (lenp / sizeof(phandle)); i++) {
  374. if (vic_handles[i] == target->phandle)
  375. return spu;
  376. }
  377. }
  378. return NULL;
  379. }
  380. static void __init init_affinity_node(int cbe)
  381. {
  382. struct spu *spu, *last_spu;
  383. struct device_node *vic_dn, *last_spu_dn;
  384. phandle avoid_ph;
  385. const phandle *vic_handles;
  386. int lenp, i, added;
  387. last_spu = list_first_entry(&cbe_spu_info[cbe].spus, struct spu,
  388. cbe_list);
  389. avoid_ph = 0;
  390. for (added = 1; added < cbe_spu_info[cbe].n_spus; added++) {
  391. last_spu_dn = spu_devnode(last_spu);
  392. vic_handles = of_get_property(last_spu_dn, "vicinity", &lenp);
  393. /*
  394. * Walk through each phandle in vicinity property of the spu
  395. * (typically two vicinity phandles per spe node)
  396. */
  397. for (i = 0; i < (lenp / sizeof(phandle)); i++) {
  398. if (vic_handles[i] == avoid_ph)
  399. continue;
  400. vic_dn = of_find_node_by_phandle(vic_handles[i]);
  401. if (!vic_dn)
  402. continue;
  403. if (of_node_name_eq(vic_dn, "spe") ) {
  404. spu = devnode_spu(cbe, vic_dn);
  405. avoid_ph = last_spu_dn->phandle;
  406. } else {
  407. /*
  408. * "mic-tm" and "bif0" nodes do not have
  409. * vicinity property. So we need to find the
  410. * spe which has vic_dn as neighbour, but
  411. * skipping the one we came from (last_spu_dn)
  412. */
  413. spu = neighbour_spu(cbe, vic_dn, last_spu_dn);
  414. if (!spu)
  415. continue;
  416. if (of_node_name_eq(vic_dn, "mic-tm")) {
  417. last_spu->has_mem_affinity = 1;
  418. spu->has_mem_affinity = 1;
  419. }
  420. avoid_ph = vic_dn->phandle;
  421. }
  422. of_node_put(vic_dn);
  423. list_add_tail(&spu->aff_list, &last_spu->aff_list);
  424. last_spu = spu;
  425. break;
  426. }
  427. }
  428. }
  429. static void __init init_affinity_fw(void)
  430. {
  431. int cbe;
  432. for (cbe = 0; cbe < MAX_NUMNODES; cbe++)
  433. init_affinity_node(cbe);
  434. }
  435. static int __init init_affinity(void)
  436. {
  437. if (of_has_vicinity()) {
  438. init_affinity_fw();
  439. } else {
  440. if (of_machine_is_compatible("IBM,CPBW-1.0"))
  441. init_affinity_qs20_harcoded();
  442. else
  443. printk("No affinity configuration found\n");
  444. }
  445. return 0;
  446. }
  447. const struct spu_management_ops spu_management_of_ops = {
  448. .enumerate_spus = of_enumerate_spus,
  449. .create_spu = of_create_spu,
  450. .destroy_spu = of_destroy_spu,
  451. .enable_spu = enable_spu_by_master_run,
  452. .disable_spu = disable_spu_by_master_run,
  453. .init_affinity = init_affinity,
  454. };