Skip to content

Commit 7a9f446

Browse files
haokexinlinusw
authored andcommitted
gpio: thunderx: Switch to GPIOLIB_IRQCHIP
The main parts of this patch are from commit a7fc89f ("gpio: thunderx: Switch to GPIOLIB_IRQCHIP") and patch [1]. And also adjust thunderx_gpio_child_to_parent_hwirq() and add thunderx_gpio_populate_parent_alloc_info() to make sure that the correct hwirq are passed to the parent msi irqdomain. [1] https://patchwork.ozlabs.org/patch/1210180/ Signed-off-by: Kevin Hao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Linus Walleij <[email protected]>
1 parent 880b7cf commit 7a9f446

File tree

2 files changed

+78
-100
lines changed

2 files changed

+78
-100
lines changed

drivers/gpio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ config GPIO_THUNDERX
573573
tristate "Cavium ThunderX/OCTEON-TX GPIO"
574574
depends on ARCH_THUNDER || (64BIT && COMPILE_TEST)
575575
depends on PCI_MSI
576+
select GPIOLIB_IRQCHIP
576577
select IRQ_DOMAIN_HIERARCHY
577578
select IRQ_FASTEOI_HIERARCHY_HANDLERS
578579
help

drivers/gpio/gpio-thunderx.c

Lines changed: 77 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/module.h>
1616
#include <linux/pci.h>
1717
#include <linux/spinlock.h>
18+
#include <asm-generic/msi.h>
1819

1920

2021
#define GPIO_RX_DAT 0x0
@@ -53,7 +54,6 @@ struct thunderx_line {
5354
struct thunderx_gpio {
5455
struct gpio_chip chip;
5556
u8 __iomem *register_base;
56-
struct irq_domain *irqd;
5757
struct msix_entry *msix_entries; /* per line MSI-X */
5858
struct thunderx_line *line_entries; /* per line irq info */
5959
raw_spinlock_t lock;
@@ -286,54 +286,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
286286
}
287287
}
288288

289-
static void thunderx_gpio_irq_ack(struct irq_data *data)
289+
static void thunderx_gpio_irq_ack(struct irq_data *d)
290290
{
291-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
291+
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
292+
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
292293

293294
writeq(GPIO_INTR_INTR,
294-
txline->txgpio->register_base + intr_reg(txline->line));
295+
txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
295296
}
296297

297-
static void thunderx_gpio_irq_mask(struct irq_data *data)
298+
static void thunderx_gpio_irq_mask(struct irq_data *d)
298299
{
299-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
300+
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
301+
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
300302

301303
writeq(GPIO_INTR_ENA_W1C,
302-
txline->txgpio->register_base + intr_reg(txline->line));
304+
txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
303305
}
304306

305-
static void thunderx_gpio_irq_mask_ack(struct irq_data *data)
307+
static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
306308
{
307-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
309+
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
310+
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
308311

309312
writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
310-
txline->txgpio->register_base + intr_reg(txline->line));
313+
txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
311314
}
312315

313-
static void thunderx_gpio_irq_unmask(struct irq_data *data)
316+
static void thunderx_gpio_irq_unmask(struct irq_data *d)
314317
{
315-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
318+
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
319+
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
316320

317321
writeq(GPIO_INTR_ENA_W1S,
318-
txline->txgpio->register_base + intr_reg(txline->line));
322+
txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
319323
}
320324

321-
static int thunderx_gpio_irq_set_type(struct irq_data *data,
325+
static int thunderx_gpio_irq_set_type(struct irq_data *d,
322326
unsigned int flow_type)
323327
{
324-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
325-
struct thunderx_gpio *txgpio = txline->txgpio;
328+
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
329+
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
330+
struct thunderx_line *txline =
331+
&txgpio->line_entries[irqd_to_hwirq(d)];
326332
u64 bit_cfg;
327333

328-
irqd_set_trigger_type(data, flow_type);
334+
irqd_set_trigger_type(d, flow_type);
329335

330336
bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
331337

332338
if (flow_type & IRQ_TYPE_EDGE_BOTH) {
333-
irq_set_handler_locked(data, handle_fasteoi_ack_irq);
339+
irq_set_handler_locked(d, handle_fasteoi_ack_irq);
334340
bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
335341
} else {
336-
irq_set_handler_locked(data, handle_fasteoi_mask_irq);
342+
irq_set_handler_locked(d, handle_fasteoi_mask_irq);
337343
}
338344

339345
raw_spin_lock(&txgpio->lock);
@@ -362,33 +368,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data)
362368
irq_chip_disable_parent(data);
363369
}
364370

365-
static int thunderx_gpio_irq_request_resources(struct irq_data *data)
366-
{
367-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
368-
struct thunderx_gpio *txgpio = txline->txgpio;
369-
int r;
370-
371-
r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
372-
if (r)
373-
return r;
374-
375-
r = irq_chip_request_resources_parent(data);
376-
if (r)
377-
gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
378-
379-
return r;
380-
}
381-
382-
static void thunderx_gpio_irq_release_resources(struct irq_data *data)
383-
{
384-
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
385-
struct thunderx_gpio *txgpio = txline->txgpio;
386-
387-
irq_chip_release_resources_parent(data);
388-
389-
gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
390-
}
391-
392371
/*
393372
* Interrupts are chained from underlying MSI-X vectors. We have
394373
* these irq_chip functions to be able to handle level triggering
@@ -405,48 +384,42 @@ static struct irq_chip thunderx_gpio_irq_chip = {
405384
.irq_unmask = thunderx_gpio_irq_unmask,
406385
.irq_eoi = irq_chip_eoi_parent,
407386
.irq_set_affinity = irq_chip_set_affinity_parent,
408-
.irq_request_resources = thunderx_gpio_irq_request_resources,
409-
.irq_release_resources = thunderx_gpio_irq_release_resources,
410387
.irq_set_type = thunderx_gpio_irq_set_type,
411388

412389
.flags = IRQCHIP_SET_TYPE_MASKED
413390
};
414391

415-
static int thunderx_gpio_irq_translate(struct irq_domain *d,
416-
struct irq_fwspec *fwspec,
417-
irq_hw_number_t *hwirq,
418-
unsigned int *type)
392+
static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
393+
unsigned int child,
394+
unsigned int child_type,
395+
unsigned int *parent,
396+
unsigned int *parent_type)
419397
{
420-
struct thunderx_gpio *txgpio = d->host_data;
398+
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
399+
struct irq_data *irqd;
400+
unsigned int irq;
421401

422-
if (WARN_ON(fwspec->param_count < 2))
402+
irq = txgpio->msix_entries[child].vector;
403+
irqd = irq_domain_get_irq_data(gc->irq.parent_domain, irq);
404+
if (!irqd)
423405
return -EINVAL;
424-
if (fwspec->param[0] >= txgpio->chip.ngpio)
425-
return -EINVAL;
426-
*hwirq = fwspec->param[0];
427-
*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
406+
*parent = irqd_to_hwirq(irqd);
407+
*parent_type = IRQ_TYPE_LEVEL_HIGH;
428408
return 0;
429409
}
430410

431-
static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq,
432-
unsigned int nr_irqs, void *arg)
411+
static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip,
412+
unsigned int parent_hwirq,
413+
unsigned int parent_type)
433414
{
434-
struct thunderx_line *txline = arg;
435-
436-
return irq_domain_set_hwirq_and_chip(d, virq, txline->line,
437-
&thunderx_gpio_irq_chip, txline);
438-
}
439-
440-
static const struct irq_domain_ops thunderx_gpio_irqd_ops = {
441-
.alloc = thunderx_gpio_irq_alloc,
442-
.translate = thunderx_gpio_irq_translate
443-
};
415+
msi_alloc_info_t *info;
444416

445-
static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
446-
{
447-
struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
417+
info = kmalloc(sizeof(*info), GFP_KERNEL);
418+
if (!info)
419+
return NULL;
448420

449-
return irq_find_mapping(txgpio->irqd, offset);
421+
info->hwirq = parent_hwirq;
422+
return info;
450423
}
451424

452425
static int thunderx_gpio_probe(struct pci_dev *pdev,
@@ -456,6 +429,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
456429
struct device *dev = &pdev->dev;
457430
struct thunderx_gpio *txgpio;
458431
struct gpio_chip *chip;
432+
struct gpio_irq_chip *girq;
459433
int ngpio, i;
460434
int err = 0;
461435

@@ -500,8 +474,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
500474
}
501475

502476
txgpio->msix_entries = devm_kcalloc(dev,
503-
ngpio, sizeof(struct msix_entry),
504-
GFP_KERNEL);
477+
ngpio, sizeof(struct msix_entry),
478+
GFP_KERNEL);
505479
if (!txgpio->msix_entries) {
506480
err = -ENOMEM;
507481
goto out;
@@ -542,27 +516,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
542516
if (err < 0)
543517
goto out;
544518

545-
/*
546-
* Push GPIO specific irqdomain on hierarchy created as a side
547-
* effect of the pci_enable_msix()
548-
*/
549-
txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain,
550-
0, 0, of_node_to_fwnode(dev->of_node),
551-
&thunderx_gpio_irqd_ops, txgpio);
552-
if (!txgpio->irqd) {
553-
err = -ENOMEM;
554-
goto out;
555-
}
556-
557-
/* Push on irq_data and the domain for each line. */
558-
for (i = 0; i < ngpio; i++) {
559-
err = irq_domain_push_irq(txgpio->irqd,
560-
txgpio->msix_entries[i].vector,
561-
&txgpio->line_entries[i]);
562-
if (err < 0)
563-
dev_err(dev, "irq_domain_push_irq: %d\n", err);
564-
}
565-
566519
chip->label = KBUILD_MODNAME;
567520
chip->parent = dev;
568521
chip->owner = THIS_MODULE;
@@ -577,11 +530,35 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
577530
chip->set = thunderx_gpio_set;
578531
chip->set_multiple = thunderx_gpio_set_multiple;
579532
chip->set_config = thunderx_gpio_set_config;
580-
chip->to_irq = thunderx_gpio_to_irq;
533+
girq = &chip->irq;
534+
girq->chip = &thunderx_gpio_irq_chip;
535+
girq->fwnode = of_node_to_fwnode(dev->of_node);
536+
girq->parent_domain =
537+
irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
538+
girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
539+
girq->populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info;
540+
girq->handler = handle_bad_irq;
541+
girq->default_type = IRQ_TYPE_NONE;
542+
581543
err = devm_gpiochip_add_data(dev, chip, txgpio);
582544
if (err)
583545
goto out;
584546

547+
/* Push on irq_data and the domain for each line. */
548+
for (i = 0; i < ngpio; i++) {
549+
struct irq_fwspec fwspec;
550+
551+
fwspec.fwnode = of_node_to_fwnode(dev->of_node);
552+
fwspec.param_count = 2;
553+
fwspec.param[0] = i;
554+
fwspec.param[1] = IRQ_TYPE_NONE;
555+
err = irq_domain_push_irq(girq->domain,
556+
txgpio->msix_entries[i].vector,
557+
&fwspec);
558+
if (err < 0)
559+
dev_err(dev, "irq_domain_push_irq: %d\n", err);
560+
}
561+
585562
dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
586563
ngpio, chip->base);
587564
return 0;
@@ -596,10 +573,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev)
596573
struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
597574

598575
for (i = 0; i < txgpio->chip.ngpio; i++)
599-
irq_domain_pop_irq(txgpio->irqd,
576+
irq_domain_pop_irq(txgpio->chip.irq.domain,
600577
txgpio->msix_entries[i].vector);
601578

602-
irq_domain_remove(txgpio->irqd);
579+
irq_domain_remove(txgpio->chip.irq.domain);
603580

604581
pci_set_drvdata(pdev, NULL);
605582
}

0 commit comments

Comments
 (0)