.. | .. |
---|
38 | 38 | #define CONFIG_FSL_DPA_PIRQ_FAST 1 |
---|
39 | 39 | |
---|
40 | 40 | static struct cpumask portal_cpus; |
---|
| 41 | +static int __qman_portals_probed; |
---|
41 | 42 | /* protect qman global registers and global data shared among portals */ |
---|
42 | 43 | static DEFINE_SPINLOCK(qman_lock); |
---|
43 | 44 | |
---|
.. | .. |
---|
195 | 196 | if (p) { |
---|
196 | 197 | pcfg = qman_get_qm_portal_config(p); |
---|
197 | 198 | if (pcfg) { |
---|
198 | | - irq_set_affinity(pcfg->irq, cpumask_of(0)); |
---|
199 | | - qman_portal_update_sdest(pcfg, 0); |
---|
| 199 | + /* select any other online CPU */ |
---|
| 200 | + cpu = cpumask_any_but(cpu_online_mask, cpu); |
---|
| 201 | + irq_set_affinity(pcfg->irq, cpumask_of(cpu)); |
---|
| 202 | + qman_portal_update_sdest(pcfg, cpu); |
---|
200 | 203 | } |
---|
201 | 204 | } |
---|
202 | 205 | return 0; |
---|
.. | .. |
---|
218 | 221 | return 0; |
---|
219 | 222 | } |
---|
220 | 223 | |
---|
| 224 | +int qman_portals_probed(void) |
---|
| 225 | +{ |
---|
| 226 | + return __qman_portals_probed; |
---|
| 227 | +} |
---|
| 228 | +EXPORT_SYMBOL_GPL(qman_portals_probed); |
---|
| 229 | + |
---|
221 | 230 | static int qman_portal_probe(struct platform_device *pdev) |
---|
222 | 231 | { |
---|
223 | 232 | struct device *dev = &pdev->dev; |
---|
224 | 233 | struct device_node *node = dev->of_node; |
---|
225 | 234 | struct qm_portal_config *pcfg; |
---|
226 | 235 | struct resource *addr_phys[2]; |
---|
227 | | - int irq, cpu, err; |
---|
| 236 | + int irq, cpu, err, i; |
---|
228 | 237 | u32 val; |
---|
229 | 238 | |
---|
230 | 239 | err = qman_is_probed(); |
---|
.. | .. |
---|
236 | 245 | } |
---|
237 | 246 | |
---|
238 | 247 | pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); |
---|
239 | | - if (!pcfg) |
---|
| 248 | + if (!pcfg) { |
---|
| 249 | + __qman_portals_probed = -1; |
---|
240 | 250 | return -ENOMEM; |
---|
| 251 | + } |
---|
241 | 252 | |
---|
242 | 253 | pcfg->dev = dev; |
---|
243 | 254 | |
---|
.. | .. |
---|
245 | 256 | DPAA_PORTAL_CE); |
---|
246 | 257 | if (!addr_phys[0]) { |
---|
247 | 258 | dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node); |
---|
248 | | - return -ENXIO; |
---|
| 259 | + goto err_ioremap1; |
---|
249 | 260 | } |
---|
250 | 261 | |
---|
251 | 262 | addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM, |
---|
252 | 263 | DPAA_PORTAL_CI); |
---|
253 | 264 | if (!addr_phys[1]) { |
---|
254 | 265 | dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node); |
---|
255 | | - return -ENXIO; |
---|
| 266 | + goto err_ioremap1; |
---|
256 | 267 | } |
---|
257 | 268 | |
---|
258 | 269 | err = of_property_read_u32(node, "cell-index", &val); |
---|
259 | 270 | if (err) { |
---|
260 | 271 | dev_err(dev, "Can't get %pOF property 'cell-index'\n", node); |
---|
| 272 | + __qman_portals_probed = -1; |
---|
261 | 273 | return err; |
---|
262 | 274 | } |
---|
263 | 275 | pcfg->channel = val; |
---|
264 | 276 | pcfg->cpu = -1; |
---|
265 | 277 | irq = platform_get_irq(pdev, 0); |
---|
266 | | - if (irq <= 0) { |
---|
267 | | - dev_err(dev, "Can't get %pOF IRQ\n", node); |
---|
268 | | - return -ENXIO; |
---|
269 | | - } |
---|
| 278 | + if (irq <= 0) |
---|
| 279 | + goto err_ioremap1; |
---|
270 | 280 | pcfg->irq = irq; |
---|
271 | 281 | |
---|
272 | 282 | pcfg->addr_virt_ce = memremap(addr_phys[0]->start, |
---|
.. | .. |
---|
289 | 299 | spin_lock(&qman_lock); |
---|
290 | 300 | cpu = cpumask_next_zero(-1, &portal_cpus); |
---|
291 | 301 | if (cpu >= nr_cpu_ids) { |
---|
| 302 | + __qman_portals_probed = 1; |
---|
292 | 303 | /* unassigned portal, skip init */ |
---|
293 | 304 | spin_unlock(&qman_lock); |
---|
294 | 305 | return 0; |
---|
.. | .. |
---|
312 | 323 | if (!cpu_online(cpu)) |
---|
313 | 324 | qman_offline_cpu(cpu); |
---|
314 | 325 | |
---|
| 326 | + if (__qman_portals_probed == 1 && qman_requires_cleanup()) { |
---|
| 327 | + /* |
---|
| 328 | + * QMan wasn't reset prior to boot (Kexec for example) |
---|
| 329 | + * Empty all the frame queues so they are in reset state |
---|
| 330 | + */ |
---|
| 331 | + for (i = 0; i < qm_get_fqid_maxcnt(); i++) { |
---|
| 332 | + err = qman_shutdown_fq(i); |
---|
| 333 | + if (err) { |
---|
| 334 | + dev_err(dev, "Failed to shutdown frame queue %d\n", |
---|
| 335 | + i); |
---|
| 336 | + goto err_portal_init; |
---|
| 337 | + } |
---|
| 338 | + } |
---|
| 339 | + qman_done_cleanup(); |
---|
| 340 | + } |
---|
| 341 | + |
---|
315 | 342 | return 0; |
---|
316 | 343 | |
---|
317 | 344 | err_portal_init: |
---|
.. | .. |
---|
319 | 346 | err_ioremap2: |
---|
320 | 347 | memunmap(pcfg->addr_virt_ce); |
---|
321 | 348 | err_ioremap1: |
---|
| 349 | + __qman_portals_probed = -1; |
---|
| 350 | + |
---|
322 | 351 | return -ENXIO; |
---|
323 | 352 | } |
---|
324 | 353 | |
---|