1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include "bman_priv.h"
32
33static struct bman_portal *affine_bportals[NR_CPUS];
34static struct cpumask portal_cpus;
35
36static DEFINE_SPINLOCK(bman_lock);
37
38static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg)
39{
40 struct bman_portal *p = bman_create_affine_portal(pcfg);
41
42 if (!p) {
43 dev_crit(pcfg->dev, "%s: Portal failure on cpu %d\n",
44 __func__, pcfg->cpu);
45 return NULL;
46 }
47
48 bman_p_irqsource_add(p, BM_PIRQ_RCRI);
49 affine_bportals[pcfg->cpu] = p;
50
51 dev_info(pcfg->dev, "Portal initialised, cpu %d\n", pcfg->cpu);
52
53 return p;
54}
55
56static int bman_offline_cpu(unsigned int cpu)
57{
58 struct bman_portal *p = affine_bportals[cpu];
59 const struct bm_portal_config *pcfg;
60
61 if (!p)
62 return 0;
63
64 pcfg = bman_get_bm_portal_config(p);
65 if (!pcfg)
66 return 0;
67
68
69 cpu = cpumask_any_but(cpu_online_mask, cpu);
70 irq_set_affinity(pcfg->irq, cpumask_of(cpu));
71 return 0;
72}
73
74static int bman_online_cpu(unsigned int cpu)
75{
76 struct bman_portal *p = affine_bportals[cpu];
77 const struct bm_portal_config *pcfg;
78
79 if (!p)
80 return 0;
81
82 pcfg = bman_get_bm_portal_config(p);
83 if (!pcfg)
84 return 0;
85
86 irq_set_affinity(pcfg->irq, cpumask_of(cpu));
87 return 0;
88}
89
90static int bman_portal_probe(struct platform_device *pdev)
91{
92 struct device *dev = &pdev->dev;
93 struct device_node *node = dev->of_node;
94 struct bm_portal_config *pcfg;
95 struct resource *addr_phys[2];
96 int irq, cpu, err;
97
98 err = bman_is_probed();
99 if (!err)
100 return -EPROBE_DEFER;
101 if (err < 0) {
102 dev_err(&pdev->dev, "failing probe due to bman probe error\n");
103 return -ENODEV;
104 }
105
106 pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
107 if (!pcfg)
108 return -ENOMEM;
109
110 pcfg->dev = dev;
111
112 addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
113 DPAA_PORTAL_CE);
114 if (!addr_phys[0]) {
115 dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
116 return -ENXIO;
117 }
118
119 addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
120 DPAA_PORTAL_CI);
121 if (!addr_phys[1]) {
122 dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
123 return -ENXIO;
124 }
125
126 pcfg->cpu = -1;
127
128 irq = platform_get_irq(pdev, 0);
129 if (irq <= 0) {
130 dev_err(dev, "Can't get %pOF IRQ'\n", node);
131 return -ENXIO;
132 }
133 pcfg->irq = irq;
134
135 pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
136 resource_size(addr_phys[0]),
137 QBMAN_MEMREMAP_ATTR);
138 if (!pcfg->addr_virt_ce) {
139 dev_err(dev, "memremap::CE failed\n");
140 goto err_ioremap1;
141 }
142
143 pcfg->addr_virt_ci = ioremap(addr_phys[1]->start,
144 resource_size(addr_phys[1]));
145 if (!pcfg->addr_virt_ci) {
146 dev_err(dev, "ioremap::CI failed\n");
147 goto err_ioremap2;
148 }
149
150 spin_lock(&bman_lock);
151 cpu = cpumask_next_zero(-1, &portal_cpus);
152 if (cpu >= nr_cpu_ids) {
153
154 spin_unlock(&bman_lock);
155 return 0;
156 }
157
158 cpumask_set_cpu(cpu, &portal_cpus);
159 spin_unlock(&bman_lock);
160 pcfg->cpu = cpu;
161
162 if (!init_pcfg(pcfg)) {
163 dev_err(dev, "portal init failed\n");
164 goto err_portal_init;
165 }
166
167
168 if (!cpu_online(cpu))
169 bman_offline_cpu(cpu);
170
171 return 0;
172
173err_portal_init:
174 iounmap(pcfg->addr_virt_ci);
175err_ioremap2:
176 memunmap(pcfg->addr_virt_ce);
177err_ioremap1:
178 return -ENXIO;
179}
180
181static const struct of_device_id bman_portal_ids[] = {
182 {
183 .compatible = "fsl,bman-portal",
184 },
185 {}
186};
187MODULE_DEVICE_TABLE(of, bman_portal_ids);
188
189static struct platform_driver bman_portal_driver = {
190 .driver = {
191 .name = KBUILD_MODNAME,
192 .of_match_table = bman_portal_ids,
193 },
194 .probe = bman_portal_probe,
195};
196
197static int __init bman_portal_driver_register(struct platform_driver *drv)
198{
199 int ret;
200
201 ret = platform_driver_register(drv);
202 if (ret < 0)
203 return ret;
204
205 ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
206 "soc/qbman_portal:online",
207 bman_online_cpu, bman_offline_cpu);
208 if (ret < 0) {
209 pr_err("bman: failed to register hotplug callbacks.\n");
210 platform_driver_unregister(drv);
211 return ret;
212 }
213 return 0;
214}
215
216module_driver(bman_portal_driver,
217 bman_portal_driver_register, platform_driver_unregister);
218