| .. | .. |
|---|
| 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 | |
|---|