14
14
15
15
#include <asm/pci/bridge.h>
16
16
#include <asm/paccess.h>
17
- #include <asm/sn/intr .h>
17
+ #include <asm/sn/irq_alloc .h>
18
18
19
19
/*
20
20
* Most of the IOC3 PCI config register aren't present
@@ -310,6 +310,135 @@ static struct pci_ops bridge_pci_ops = {
310
310
.write = pci_write_config ,
311
311
};
312
312
313
+ struct bridge_irq_chip_data {
314
+ struct bridge_controller * bc ;
315
+ nasid_t nasid ;
316
+ };
317
+
318
+ static int bridge_set_affinity (struct irq_data * d , const struct cpumask * mask ,
319
+ bool force )
320
+ {
321
+ #ifdef CONFIG_NUMA
322
+ struct bridge_irq_chip_data * data = d -> chip_data ;
323
+ int bit = d -> parent_data -> hwirq ;
324
+ int pin = d -> hwirq ;
325
+ nasid_t nasid ;
326
+ int ret , cpu ;
327
+
328
+ ret = irq_chip_set_affinity_parent (d , mask , force );
329
+ if (ret >= 0 ) {
330
+ cpu = cpumask_first_and (mask , cpu_online_mask );
331
+ nasid = COMPACT_TO_NASID_NODEID (cpu_to_node (cpu ));
332
+ bridge_write (data -> bc , b_int_addr [pin ].addr ,
333
+ (((data -> bc -> intr_addr >> 30 ) & 0x30000 ) |
334
+ bit | (nasid << 8 )));
335
+ bridge_read (data -> bc , b_wid_tflush );
336
+ }
337
+ return ret ;
338
+ #else
339
+ return irq_chip_set_affinity_parent (d , mask , force );
340
+ #endif
341
+ }
342
+
343
+ struct irq_chip bridge_irq_chip = {
344
+ .name = "BRIDGE" ,
345
+ .irq_mask = irq_chip_mask_parent ,
346
+ .irq_unmask = irq_chip_unmask_parent ,
347
+ .irq_set_affinity = bridge_set_affinity
348
+ };
349
+
350
+ static int bridge_domain_alloc (struct irq_domain * domain , unsigned int virq ,
351
+ unsigned int nr_irqs , void * arg )
352
+ {
353
+ struct bridge_irq_chip_data * data ;
354
+ struct irq_alloc_info * info = arg ;
355
+ int ret ;
356
+
357
+ if (nr_irqs > 1 || !info )
358
+ return - EINVAL ;
359
+
360
+ data = kzalloc (sizeof (* data ), GFP_KERNEL );
361
+ if (!data )
362
+ return - ENOMEM ;
363
+
364
+ ret = irq_domain_alloc_irqs_parent (domain , virq , nr_irqs , arg );
365
+ if (ret >= 0 ) {
366
+ data -> bc = info -> ctrl ;
367
+ data -> nasid = info -> nasid ;
368
+ irq_domain_set_info (domain , virq , info -> pin , & bridge_irq_chip ,
369
+ data , handle_level_irq , NULL , NULL );
370
+ } else {
371
+ kfree (data );
372
+ }
373
+
374
+ return ret ;
375
+ }
376
+
377
+ static void bridge_domain_free (struct irq_domain * domain , unsigned int virq ,
378
+ unsigned int nr_irqs )
379
+ {
380
+ struct irq_data * irqd = irq_domain_get_irq_data (domain , virq );
381
+
382
+ if (nr_irqs )
383
+ return ;
384
+
385
+ kfree (irqd -> chip_data );
386
+ irq_domain_free_irqs_top (domain , virq , nr_irqs );
387
+ }
388
+
389
+ static int bridge_domain_activate (struct irq_domain * domain ,
390
+ struct irq_data * irqd , bool reserve )
391
+ {
392
+ struct bridge_irq_chip_data * data = irqd -> chip_data ;
393
+ struct bridge_controller * bc = data -> bc ;
394
+ int bit = irqd -> parent_data -> hwirq ;
395
+ int pin = irqd -> hwirq ;
396
+ u32 device ;
397
+
398
+ bridge_write (bc , b_int_addr [pin ].addr ,
399
+ (((bc -> intr_addr >> 30 ) & 0x30000 ) |
400
+ bit | (data -> nasid << 8 )));
401
+ bridge_set (bc , b_int_enable , (1 << pin ));
402
+ bridge_set (bc , b_int_enable , 0x7ffffe00 ); /* more stuff in int_enable */
403
+
404
+ /*
405
+ * Enable sending of an interrupt clear packt to the hub on a high to
406
+ * low transition of the interrupt pin.
407
+ *
408
+ * IRIX sets additional bits in the address which are documented as
409
+ * reserved in the bridge docs.
410
+ */
411
+ bridge_set (bc , b_int_mode , (1UL << pin ));
412
+
413
+ /*
414
+ * We assume the bridge to have a 1:1 mapping between devices
415
+ * (slots) and intr pins.
416
+ */
417
+ device = bridge_read (bc , b_int_device );
418
+ device &= ~(7 << (pin * 3 ));
419
+ device |= (pin << (pin * 3 ));
420
+ bridge_write (bc , b_int_device , device );
421
+
422
+ bridge_read (bc , b_wid_tflush );
423
+ return 0 ;
424
+ }
425
+
426
+ static void bridge_domain_deactivate (struct irq_domain * domain ,
427
+ struct irq_data * irqd )
428
+ {
429
+ struct bridge_irq_chip_data * data = irqd -> chip_data ;
430
+
431
+ bridge_clr (data -> bc , b_int_enable , (1 << irqd -> hwirq ));
432
+ bridge_read (data -> bc , b_wid_tflush );
433
+ }
434
+
435
+ static const struct irq_domain_ops bridge_domain_ops = {
436
+ .alloc = bridge_domain_alloc ,
437
+ .free = bridge_domain_free ,
438
+ .activate = bridge_domain_activate ,
439
+ .deactivate = bridge_domain_deactivate
440
+ };
441
+
313
442
/*
314
443
* All observed requests have pin == 1. We could have a global here, that
315
444
* gets incremented and returned every time - unfortunately, pci_map_irq
@@ -322,11 +451,16 @@ static struct pci_ops bridge_pci_ops = {
322
451
static int bridge_map_irq (const struct pci_dev * dev , u8 slot , u8 pin )
323
452
{
324
453
struct bridge_controller * bc = BRIDGE_CONTROLLER (dev -> bus );
454
+ struct irq_alloc_info info ;
325
455
int irq ;
326
456
327
457
irq = bc -> pci_int [slot ];
328
458
if (irq == -1 ) {
329
- irq = request_bridge_irq (bc , slot );
459
+ info .ctrl = bc ;
460
+ info .nasid = bc -> nasid ;
461
+ info .pin = slot ;
462
+
463
+ irq = irq_domain_alloc_irqs (bc -> domain , 1 , bc -> nasid , & info );
330
464
if (irq < 0 )
331
465
return irq ;
332
466
@@ -337,18 +471,34 @@ static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
337
471
338
472
static int bridge_probe (struct platform_device * pdev )
339
473
{
474
+ struct xtalk_bridge_platform_data * bd = dev_get_platdata (& pdev -> dev );
340
475
struct device * dev = & pdev -> dev ;
341
476
struct bridge_controller * bc ;
342
477
struct pci_host_bridge * host ;
478
+ struct irq_domain * domain , * parent ;
479
+ struct fwnode_handle * fn ;
343
480
int slot ;
344
481
int err ;
345
- struct xtalk_bridge_platform_data * bd = dev_get_platdata (& pdev -> dev );
482
+
483
+ parent = irq_get_default_host ();
484
+ if (!parent )
485
+ return - ENODEV ;
486
+ fn = irq_domain_alloc_named_fwnode ("BRIDGE" );
487
+ if (!fn )
488
+ return - ENOMEM ;
489
+ domain = irq_domain_create_hierarchy (parent , 0 , 8 , fn ,
490
+ & bridge_domain_ops , NULL );
491
+ irq_domain_free_fwnode (fn );
492
+ if (!domain )
493
+ return - ENOMEM ;
346
494
347
495
pci_set_flags (PCI_PROBE_ONLY );
348
496
349
497
host = devm_pci_alloc_host_bridge (dev , sizeof (* bc ));
350
- if (!host )
351
- return - ENOMEM ;
498
+ if (!host ) {
499
+ err = - ENOMEM ;
500
+ goto err_remove_domain ;
501
+ }
352
502
353
503
bc = pci_host_bridge_priv (host );
354
504
@@ -357,15 +507,15 @@ static int bridge_probe(struct platform_device *pdev)
357
507
bc -> busn .end = 0xff ;
358
508
bc -> busn .flags = IORESOURCE_BUS ;
359
509
510
+ bc -> domain = domain ;
511
+
360
512
pci_add_resource_offset (& host -> windows , & bd -> mem , bd -> mem_offset );
361
513
pci_add_resource_offset (& host -> windows , & bd -> io , bd -> io_offset );
362
514
pci_add_resource (& host -> windows , & bc -> busn );
363
515
364
516
err = devm_request_pci_bus_resources (dev , & host -> windows );
365
- if (err < 0 ) {
366
- pci_free_resource_list (& host -> windows );
367
- return err ;
368
- }
517
+ if (err < 0 )
518
+ goto err_free_resource ;
369
519
370
520
bc -> nasid = bd -> nasid ;
371
521
@@ -419,20 +569,28 @@ static int bridge_probe(struct platform_device *pdev)
419
569
420
570
err = pci_scan_root_bus_bridge (host );
421
571
if (err < 0 )
422
- return err ;
572
+ goto err_free_resource ;
423
573
424
574
pci_bus_claim_resources (host -> bus );
425
575
pci_bus_add_devices (host -> bus );
426
576
427
577
platform_set_drvdata (pdev , host -> bus );
428
578
429
579
return 0 ;
580
+
581
+ err_free_resource :
582
+ pci_free_resource_list (& host -> windows );
583
+ err_remove_domain :
584
+ irq_domain_remove (domain );
585
+ return err ;
430
586
}
431
587
432
588
static int bridge_remove (struct platform_device * pdev )
433
589
{
434
590
struct pci_bus * bus = platform_get_drvdata (pdev );
591
+ struct bridge_controller * bc = BRIDGE_CONTROLLER (bus );
435
592
593
+ irq_domain_remove (bc -> domain );
436
594
pci_lock_rescan_remove ();
437
595
pci_stop_root_bus (bus );
438
596
pci_remove_root_bus (bus );
0 commit comments